blueyi's notes

Follow Excellence,Success will chase you!

0%

fork

Linux多进程编程中的可以使用fork函数来创建子进程。fork函数定义在头文件unistd.h中(uni表示unix,std当然是标准库,所以很好记),该函数的声明为pid_t fork(void)其中函数的返回值类型为pid_t,可以理解为一个整型,返回值具体为:

  • 在父进程中,fork返回新创建的子进程的进程ID;
  • 在子进程中,fork返回0;
  • 如果创建子进程失败,则返回一个负值

具体创建的子进程与父进程的关系,很显示fork函数不能接受任何参数,它只简单地将父进程的几乎所有资源全部复制给子进程,然后就相当于父进程的一个副本运行,且无法与父进行共享数据。
具体 来说使用fork函数得到的子进程从父进程继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。
子进程与父进程的区别在于:

  • 父进程设置的锁,子进程不继承(因为如果是排它锁,被继承的话,矛盾了)
  • 各自的进程ID和父进程ID不同
  • 子进程的未决告警被清除;
  • 子进程的未决信号集设置为空集。
Read more »

Linux下链接分两种,即硬链接(Hard link)和软链接(Symbolic link)。当然windows下面也有软链接、硬链接之分。
为了区分硬链接和软链接,首先需要清楚Linux系统中一切皆文件,文件由两个部分组成:用户数据,即数据块和元数据,即保存文件附加属性的数据(文件大小、创建时间、inode等)。Linux系统下的同一个文件系统中,每个文件都有一个唯一的inode(索引结点)号,inode才是文件的唯一标识,在访问文件时实际上都是通过inode号来访问文件的实际数据块。
硬链接和软件链接在访问时都共用一个目标数据块,主要区别就是每个硬链接相当于一个是一个指针,该指针指向同一个inode号,只要一个文件有任意一个硬链接存在,那么该文件就可以直接通过文件的硬链接访问,也就是说当删除一个硬链接时,并不影响其他硬链接来访问文件,硬链接本身并没有单独的inode号,同一个文件的硬链接都共用一个inode号只是文件名不同,甚至可以理解为我们在linux中使用ls看到的文件本身也就是某个数据块的一个硬链接。所以当使用mv命令移动这些硬链接时,并不影响对文件的访问,因为inode都一样。
而软链接即符号链接,软链接本身就是个独立的完整文件,相当于windows下的快捷方式,有自己的inode号,只是在访问该软链接时,会被转发为访问其链接到的实际文件,当删除软链接时,并不影响实际文件,甚至删除所有的软链接对实际文件也没有影响。当删除或移动实际文件时,都将无法通过软链接访问到该文件。

Read more »

C/C++中一些之前的学习中没有涉及到和容易模糊的知识点。
其他专题标签链接:C++拾遗

构造函数中需要初始化列表初始化的成员

在构造函数中需要初始化列表初始化的有如下三种情况

  1. 带有const修饰的类成员 ,如const int a
  2. 引用成员数据,如 int &p; (可以参见这里C/C++拾遗之类成员含引用变量
  3. 带有引用的类变量 (例如类A中含有有引用成员,类B中定义的类型为A的变量)

static 修饰的变量在类外初始化,const修饰的在参数列表初始化

Read more »

C++11中提供了两种可以实现可变参数的函数实现方式:initializer_list的标准模板类型和可变参数模板。C语言中可以通过省略符类型实现可变数量的参数函数(推荐只有在需要与C函数交互时才使用些方式)。

initializer_list形参

C++11中的头文件initializer_list中提供了一种标准库类型initializer_list类型,通过该模板可以实现全部实参类型都相同的可变参数函数。使用时只需要将initializer_list类型的参数作为函数形参即可,因为initializer_list可以接受多个元素作为初始化列表,相当于一个变长数组,然后在函数中通过initializer_list头文件中提供的相应函数获取其中的元素即可。initializer_list提供的操作有:

Read more »

extern “C”的主要作用是让C++中的函数名字使用C语言的编译处理方式(也就是在编译阶段,确切来说 是汇编阶段不对函数名进行mangle处理),这样就可以让C语言代码能够通过“与C语言兼容的方式声明的头文件”来链接C++编译器生成的二进制格式文件中函数。由于C++支持函数重载,而C语言不支持,C++编译器为了支持函数重载,就需要为同名但参数列表不同的函数名指定一个全局唯一的名字(该名字被称为mangled name),也就是编译阶段的mangle name过程,这些名字通常会包含相应的参数列表类型等,不同的编译器实现不同。
由于有extern的修饰,表示被修饰的变量或函数的对外部文件可见,或其定义来自其他文件中,与static的作用刚好相反。
SOF上的回答:http://stackoverflow.com/questions/1041866/in-c-source-what-is-the-effect-of-extern-c

Read more »

条件编译是由一批预处理器指令,通过指定一些限定的条件,有选择性地对源代码进行预处理,从而实现条件编译。后续的编译、链接等过程都是在预处理之后的代码上进行的,所以预处理之后的代码通常要精简很多(这里精简的思想是包含那个引入的头文件的),无意义的编译指令,根据条件编译代码不需要编译的代码,还有注释都会有预处理之后忽略掉。常用的预的处理器指令主要有(方括号中为后面需要跟的内容):

Read more »

深拷贝(Deep copy)和浅拷贝(Shallow copy)是指对于类或结构体这类复合类型的变量,当它们的成员变量中含有指针时,在赋值或初始化的过程中,如果只是修改指针的指向,则属于浅拷贝(也称位拷贝)。因为此时指针所指向的实际内容依然只有一份,当其中一个变量销毁时,则该内存将被释放,那么此时另一个变量中将存在悬挂指针。而如果在发生拷贝时首先将需要被拷贝的内容复制到一个新的内存地址,然后再将相应的指针指向该新地址,则称为深拷贝。SOF上的一个相关回答http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy<>

首先提示:在C++中,对于类型class1来说,class1 a(b);等价于class1 a = b;都将调用拷贝构造函数进行初始化,而不是将后面的语句中使用赋值运算符对a进行赋值。如果要使用赋值运算符将b赋值给a,需要class1 a; a = b;

下面举例说明:

Read more »

C语言中static的作用

1.隐藏变量或函数。被static修饰的变量或者函数,对其他文件是不可见的
如果变量或函数没有被static修饰,那么一个文件可以通过extern关键字来引用在另一个变量中声明的变量或函数。如:

Read more »

位字段(bit field)也称位域,是一个由signed int 或 unsigned int中一组相邻的位 (C99 还允许 _Bool类型的位字段). 位字段由一个结构体声明建立, 该结构声明为每个字段提供标签, 并决定字段的宽度。使用位字段可以将有些仅需要很少的变量范围的值压缩到一个较小的结构体中。
声明时需要在变量名后面跟冒号(:),冒号后面跟上需要设置的它的位宽度。
或者在在类型名后面跟冒号再跟位宽度,用于对齐占位

Read more »