作者:倪键树,华清远见嵌入式培训中心讲师。
11、wait的有一个子进程使用:如果一个进程有几个子进程,那么只要有一个子进程终止,wait就返回。
如果要等待某个特定进程的终止,则应该使用waitpid,其原型为 pid_t waitpid(pid_t pid, int *status, int options);
对于waitpid的pid参数的解释与其值有关:
1)pid == -1 等待任一子进程,与wait等效。
2)pid > 0 等待其进程ID与pid相等的子进程。
3)pid == 0 等待其组ID等于调用进程的组ID的任一进程。
4)pid < -1 等待其组ID等于pid的绝对值的任一子进程。
12、Linux守护进程的编写步骤:
1)创建子进程,父进程退出:子进程变成孤儿进程,在形式上做到了与控制终端的脱离。
2)在子进程中创建新会话:setsid函数使进程完全独立出来,脱离所有其他进程的控制。
3)改变当前目录为根目录:chdir 让“/”或“/temp”作为守护进程的当前目录,不允许被 卸载。
4)重设文件权限掩码:umask(0)文件权限掩码是指文件权限中被屏蔽掉的对应位。把文 件权限掩码设置为0,可以增加该守护进程的灵活性。
5)关闭文件描述符:关闭用不到的文件。
13、会话周期:
在Linux中,守护进程的编写步骤中,第二步:在子进程中创建新会话。
会话周期:会话期是一个或多个进程组的集合。通常,一个会话开始于用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。
接下来就可以具体介绍setsid的相关内容:
setsid函数作用:
setsid函数用于创建一个新的会话,并且担任该会话组的组长。调用setsid有下面3个作用:
——让进程摆脱原会话的控制
——让进程摆脱原进程组的控制
——让进程摆脱原终端的控制
14、那么,在创建守护进程时,为什么要调用setsid函数呢?由于创建守护进程的第一步调用了fork函数来创建子进程,再将父进程退出。由于在调用了fork函数时,子进程全盘拷贝了父进程的会话期、进程组、控制终端等,虽然父进程退出了,但会话期、进程组、控制终端等并没有改变,因此,这还不是真正意义上的独立开来,而setsid函数能够使进程完全独立出来,从而摆脱其它进程的控制。
15、ftruncate函数——改变文件大小
int ftruncate(int fd,off_t length);
ftruncate()会将参数fd指定的文件大小改为参数length指定的大小。
如果原来的文件大小比参数length大,则超过的部分会被删除。
执行成功则返回0,失败返回-1,错误原因存于errno。
16、lseek:移动文件读、写指针
off_t lseek(int filds,off_t offset,int whence);
whence为下列其中一种:(SEEK_SET,SEEK_CUR和SEEK_END一次为0,1和2)
SEEK_SET将读写位置指向文件头后在增加offset个位移量。
SEEK_CUR以目前的读写位置往后增加offset个位移量。
SEEK_END将读写位置指向文件尾后再增加offset个位移量。
1)欲将读写位置移到文件开头时
lseek(int fildes,0,SEEK_SET);
2)欲将读写位置移到文件尾时
lseek(int fildes,0,SEEK_END);
3)想要取得目前文件位置时
lseek(int fildes,0,SEEK_CUR);
17、处理器总处于以下三种状态之一:
1)内核态,运行于进程上下文,内核代表进程运行于内核空间;
2)内核态,运行于中断上下文,内核代表硬件运行于内核空间;
3)用户态,运行于用户空间。
18、一个进程的上下文可以分为三个部分:用户级上下文、寄存器上下文以及系统级上下文。
用户级上下文: 正文、数据、用户堆栈以及共享存储区;
寄存器上下文: 通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP);
系统级上下文: 进程控制块task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、pte)、内核栈。