8.2 进程标示
ID
为0
的进程通常是调度进程(交换进程),属于内核的一部分。ID
为1
的进程是init进程,在自举过程结束时由内核调用,该进程读写系统初始化文件,将系统引导至一个状态(如多用户)。 它是一个普通用户进程,但以超级用户特权运行。
8.3 函数fork
函数声明:
#include <unisted.h>
pid_t fork();
特性
fork
函数被调用依次,返回两次父进程的所有文件描述符被复制到子进程,即父子进程每个打开的文件描述符共享一个文件表项。一个
重点
是父子进程共享一个文件偏移量。注意子进程继承了父进程的哪些资源以及两者之间的不同
子进程的继承
-
继承
实际用户ID、有效用户ID、实际组ID、有效组ID 设置用户ID标志和设置组ID标志 附加组ID 会话ID 控制终端 当前工作目录、根目录 环境 文件模式的创建屏蔽字 共享存储段 资源限制 信号屏蔽和安排 对任一打开文件描述符的执行时关闭(close-on-exec)标志
-
不继承
进程ID 子进程的运行时间信息 父进程设置的文件锁 父进程的未处理信号集 父进程的未处理闹钟
8.4 函数 vfork
特性
在子进程调用
exec
或exit
之前,它在父进程的空间中运行vfork的使用要慎重:在子进程调用
exec
或exit
之前,子进程若修改数据,则父进程的数据也会改变。vfork保证子进程先运行,在它调用
exec
或exit
之后父进程才可能被调用运行。
8.5 函数exit
正常终止
main函数中return返回
调用exit()
调用_Exit()、_exit()
最后一个线程返回
最后一个线程调用phread_exit()
异常终止
调用abort
进程收到某些信号,使进程退出
最后一个线程对取消做出反应 pthread_cancel()
进程终止时保留的资源
进程ID
该进程的终止状态
该进程使用的CPU时间总量
僵尸进程子进程终止,但父进程没有利用wait或waitpid获取子进程终止状态
避免出现僵尸进程的方法:
---1. 用wait或waitpid回收终止进程的资源
---2. 编写如下代码
int main(){
pid_t pid1;
if ((pid = fork) == 0){ // for simplicity, not take "pid < 0" into consideration
pid_t pid2;
if ( (pid2 = fork()) == 0){
while(1){
/* grandchild func*/
}
}
exit(0);
}
if (wait(NULL) != pid1)
err_sys("wait err.");
while(1){
/*main thread func*/
}
exit(0);
}
代码示意图
child1提前终止时,child2的父进程变成了init,当child2终止时,init调用wait回收僵尸进程的资源
8.6 函数wait和waitpid
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
pid:
---1. pid == -1 ,等待任意进程
---2. pid > 0 , 等待进程pid
---3. pid == 0 , 等待本进程组的任意进程
---4. pid < -1, 等待组ID等于pid绝对值的任一进程
option:
---1. WNOTHANG 没有进程报告状态则立即返回
---2. WCONTINUED
---3. WUNTRACED 子进程由于SIGTTIN、SIGTTOU、SIGTSTP或SIGSTOP信号进入暂停状态
---4. 0
status:
返回值
wait: 唯一的出错是进程没有子进程,errno = ECHILD
waitpid: 指定的进程或进程组不存在或没有权限调用,则会出错
8.7 函数waitid
8.8 函数wait3和wait4
8.10 函数exec
六个exec最终调用execve函数
v: vector
l: list
e:environment
p:path (not pathname)
基本的进程控制原语: fork, exec, wait, exit
execl execle execlp的命令行参数格式:
char* arg0, char* arg1, ..., char* argn, (char*)0
新程序从调用进程继承的属性:
进程ID和父进程ID
实际用户ID和实际组ID
注意:SUID没有继承
添加组ID
进程组ID
对话期ID
控制终端
当前工作目录
根目录
资源限制
闹钟尚余留的时间
文件方式创建屏蔽字
文件锁
进程信号屏蔽
未决信号
tms_utime, tms_stime, tms_cutime以及tms_ustime值
8.11 更改用户ID和更改组ID
int setuid(uid_t uid);
int setgid(gid_t uid);
int seteuid(uid_t uid);
int setegid(gid_t uid);
int setreuid(uid_t ruid,uid_t euid);
int setregid(uid_t ruid,uid_t euid);
int getresuid(uid_t ruid,uid_t euid,uid_t suid);
int getresgid(uid_t rgid,uid_t egid,uid_t sgid);
ruid、euid、suid转换
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。