进程相关函数及使用
1. fork函数
-
用途:用于生成子进程
-
原型:
pid_t fork(void);
-
返回值:
父进程中:返回生成的子进程pid
子进程中:0表示成功,-1表示失败,如果失败就不会创建子进程
2. getpid与getppid
-
用途:获取进程pid
-
原型:
pid_t getpid(void); //获取当前的进程号 pid_t getppid(void); //获取父进程号
-
返回值:
对应的pid号
3. 进程共享
-
相同:全局变量、.data、.text、栈、堆、环境变量、用户ID、宿主目录、进程工作目录、信号处理方式
-
不同:进程ID、fork返回值、父进程ID、进程运行时间、定时器、未决信号集
-
规则:进程之间遵循读时共享、写时复制
-
共享:1.文件描述符(打开文件的结构体);2.mmap建立的映射区(进程间通信);
4. exec函数族
-
用途:将当前进程的代码段和数据段换为所要加载的程序的代码段和数据段,然后让进程从新的代码段第一条指令开始执行,但进程ID不变,换核不换壳。
-
execlp
-
作用:加载一个进程,借助PATH环境变量
-
原型:
int execlp(const char* file, const char* arg, ...);
-
参数
file:要加载的程序名称
-
返回值:
成功:无返回
失败:返回-1,设置errorno
-
例子:
execlp("ls", "ls", "-l", "-a", "-h", NULL); //执行ls指令
-
-
execl
-
作用:多用于加载已知路径的用户程序
-
原型:
int execl(const char* path, const char* arg, ...);
-
参数:
path:要加载的程序路径
-
返回值:
成功:无返回
失败:返回-1,设置errorno
-
例子:
execl("./a.out", "./a.out", "abc", NULL); //执行用户程序a.out execl("/bin/ls", "ls", "-l", NULL); //执行指令ls -l
-
-
exec函数族的一般规律
l(list) 命令行参数列表 p(path) 搜索file时使用path变量 v(vector) 使用命令行参数数组 e(environment) 使用环境变量数组,不使用进程原有的环境变量
5. 异常子进程
-
孤儿进程:父进程先于子进程结束,则子进程称为孤儿进程,子进程的父进程称为init进程,称init进程为孤儿领养进程
-
僵尸进程:子进程终止,父进程尚未回收,子进程残留资源存放于内核中,成为僵尸进程
6. wait函数
-
原型:
pid_t wait(int* status);
-
作用:
- 阻塞等待子进程退出
- 回收子进程残留资源
- 获取子进程结束状态(退出原因)
-
返回值:
成功:返回回收的子进程id
失败:-1
-
对于status状态值的应用:
7. waitpid函数
-
原型
pid_t waitpid(pid_t pid, int* status, int options);
-
参数:
pid:指定进程进行回收
- 大于0:回收指定的进程
- -1:回收任意的子进程
- 0:回收和当前调用waitpid同一个组的所有子进程
- 小于-1:回收指定进程组内的任意子进程
status:指示状态,传出参数
options:可选项
- WNOHANG:加上之后wait函数将不会导致阻塞
-
返回值:
大于0:返回回收的子进程pid
0:函数调用时,参3指定了WNOHANG并且没有子进程结束
-1:失败,设置errorno
-
总结:
-
waitpid和wait一次只能回收一个子进程,多个进程需要用循环来回收
-
waitpid(-1, &status, 0) == wait(&status); //两者功能等价
-
8. 会话
-
概念:多个进程组的集合,进程组又是多个进程的集合,父进程fork出子进程,那么父进程就是组长。
-
注意事项:
- 调用进程不能是进程组的组长,该进程变成新会话的首进程
- 该进程会成为一个新进程组的组长进程
- 需要有root权限
- 新会话丢弃原有的控制终端,该会话没有控制终端
- 该调用进程是组长进程,则出错返回
- 建立新会话时,先调用fork,父进程终止,子进程调用setsid。
-
相关函数
pid_t setsid(void); ps ajx //查看组id、会话id和进程id的shell指令
-
功能:将当前进程设置为新的会话,前提是当前进程不能为组长,这个新的会话是没有操作终端的
-
返回值:
成功:0
失败:-1,设置errno
-
9. 守护进程
-
概念:Daemon进程,通常运行于操作系统的后台,脱离控制终端。一般不与用户直接交互,周期性的等待某个事件发生或周期性执行某一动作。不受用户登录注销影响,通常采用以d结尾的命名方式。Linux后台的一些系统服务进程,没有控制终端,不能与系统交互。不受到用户登陆和注销的影响,这些都是守护进程比如:ftp服务器、nfs服务器等。
-
典型守护进程:httpd、sshd、vsftpd和nfsd等等,特征是都带有一个d结尾,即Daemon。
-
流程模型:
-
fork创建子进程,父进程退出,所有工作在子进程中进行形式上脱离了控制终端
-
在子进程中创建会话,利用setsid函数,使子进程独立出来,脱离控制
-
根据需要,改变当前目录位置,利用chdir函数,防止占用可卸载的文件系统
-
根据需要,重设文件权限掩码,利用umask函数, 防止继承的文件拒绝某些权限
-
根据需要,关闭文件描述符,无需操作终端
-
开始执行守护进程核心工作
-