创建进程
fork()
定义: pid_t fork(void); 功能: 在当前的进程中,创建一个子进程 返回值: 成功: 在父进程中:返回子进程的进程号(>0) 在子进程中:返回值为0 失败:-1,并设置errno
特点
1.子进程几乎拷贝了父进程的全部内容。包括代码、数据、系统数据段中的pc值、栈中的数据、父进程中打开的文件等;但它们的PID、PPID是不同的。
2.父子进程有独立的地址空间,互不影响;当在相应的进程中改变全局变量、静态变量,都互不影响。
3.若父进程先结束,子进程成为孤儿进程,被init进程收养,子进程变成后台进程。
4.若子进程先结束,父进程如果没有及时回收,子进程变成僵尸进程(要避免僵尸进程产生)。
5.fork()调用一次,返回两次,分别在父进程和子进程中。
示例代码
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char const *argv[]) { pid_t pid = fork(); if (pid < 0) { perror("fork error"); return -1; } else if (pid == 0) { sleep(2); printf("child process\n"); } else { sleep(2); printf("father process\n"); while(1); } return 0; }
运行程序时,父进程和子进程的执行顺序是随机的,为了不让进程结束,在父进程中加入while(1)死循环,以便用ps命令查看进程状态。
子进程的父进程号为28835。
进程回收
wait()
定义: pid_t wait(int *status); 功能: 等待子进程结束,回收子进程资源 参数: status:子进程结束时,父进程通过status参数获得子进程的终止状态 返回值: 成功:返回子进程的进程号 失败:-1,并设置errno
waitpid()
定义: pid_t waitpid(pid_t pid, int *status, int options); 功能: 等待子进程结束,回收子进程资源 参数: pid: > 0 指定子进程进程号 =-1 任意子进程 = 0 等待其组ID等于调用进程的组ID的任一子进程 <-1 等待其组ID等于pid的绝对值的任一子进程 status:子进程结束时,父进程通过status参数获得子进程的终止状态 options: WNOHANG:若没有子进程结束,立即返回,非阻塞 0:阻塞,直到子进程结束 返回值: 成功:返回子进程的进程号 失败:-1,并设置errno
非阻塞会循环执行代码,也就是轮询,这种循环执行会一直占用CPU,消耗CPU资源;而阻塞会一直等待子进程结束,直到子进程结束才返回,这种等待会消耗时间,实时性较差。
wait(NULL);等价于waitpid(pid, NULL, 0);
进程终止
exit()
定义: void exit(int status); 功能: 终止当前进程 参数: status:终止状态,父进程通过wait()或waitpid()获得子进程的终止状态
_exit()
定义: void _exit(int status); 功能: 终止当前进程 参数: status:终止状态,父进程通过wait()或waitpid()获得子进程的终止状态
exit和_exit的区别是exit会刷新缓存,_exit不会刷新缓存。参数status的值为0表示正常终止,非0表示异常终止。
获取进程ID
getpid()
定义: pid_t getpid(void); 功能: 获取当前进程的进程号 返回值: 进程号
getppid()
定义: pid_t getppid(void); 功能: 获取当前进程的父进程号 返回值: 父进程号
守护进程
特点
1.在后台运行,不受终端的影响;
2.生命周期较长,在系统启动时开启,系统关闭退出;
3.查看进程状态时,“?”表示守护进程。
创建守护进程
1.fork()创建子进程,父进程退出,子进程成为孤儿进程
2.使用setsid()创建新的会话,使子进程成为新的会话组长,脱离终端
3.chdir("/"),使子进程工作目录切换到根目录
4.umask(0)设置文件权限掩码,提高灵活性
5.守护进程不需要和用户交互,因此关闭标准输入、输出、错误,即close(0)、close(1)、close(2)
示例代码:
创建守护进程实现每秒向文件中写入字符串“hello”
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <stdlib.h> int main(int argc, char const *argv[]) { pid_t pid = fork(); if (pid < 0) { perror("fork error"); return -1; } else if (pid == 0) { FILE *fp=fopen("./text.txt","a+"); setsid(); chdir("/"); umask(0); close(0); close(1); while (1) { fputs("hello\n",fp); fflush(fp); sleep(1); } } else exit(0); return 0; }
运行程序,查看进程状态:
实验完毕后记得使用kill命令杀掉进程,否则会一直运行,影响系统运行效率。