1. 创建一个子进程
-
程序demo #include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
pid_t getpid(void);
pid_t getppid(void);
-
fork函数返回值: 失败 返回 -1 成功 两次返回 ? 父进程返回子进程的 pid_t ? 子进程返回 0 -
创建一个子进程的程序: #include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Begin ..\n");
pid_t pid = fork();
if (pid < 0) {
perror("fork err\n");
exit(1);
}
if (pid == 0) {
printf("I am a Child, pid = %d, ppid = %d \n", getpid(), getppid());
} else if (pid > 0) {
printf("I am a Parent, childpid = %d, selfpid = %d, ppid = %d \n",
pid, getpid(), getppid());
sleep(1);
}
printf("End ...\n");
return 0;
}
-
输出结果 Begin ..
I am a Parent, childpid = 73714, selfpid = 73713, ppid = 73479
I am a Child, pid = 73714, ppid = 73713
End ...
End ...
-
为什么会执行两次printf(“End …\n”)函数呢? 在fork函数生成子进程之后,父进程和子进程都会执行fork语句之后的代码。 -
补充:linux查看进程信息的命令 查看进程信息:ps aux 查看进程组信息:ps ajx 给进程发送一个信号:kill 杀死一个进程:kill -9 pid
2. 创建多个子进程
-
创建多个子进程的程序: int main()
{
printf("Begin ..\n");
for (int i = 0; i < 5; i++) {
pid_t pid = fork();
if (pid < 0) {
perror("fork err\n");
exit(1);
}
if (pid == 0) {
printf("I am a Child, pid = %d, ppid = %d \n", getpid(), getppid());
break;
} else if (pid > 0) {
printf("I am a Parent, childpid = %d, selfpid = %d, ppid = %d \n",
pid, getpid(), getppid());
sleep(1);
}
}
printf("End ...\n");
return 0;
}
-
执行结果: Begin ..
I am a Parent, childpid = 74179, selfpid = 74178, ppid = 73479
I am a Child, pid = 74179, ppid = 74178
End ...
I am a Parent, childpid = 74182, selfpid = 74178, ppid = 73479
I am a Child, pid = 74182, ppid = 74178
End ...
I am a Parent, childpid = 74192, selfpid = 74178, ppid = 73479
I am a Child, pid = 74192, ppid = 74178
End ...
I am a Parent, childpid = 74202, selfpid = 74178, ppid = 73479
I am a Child, pid = 74202, ppid = 74178
End ...
I am a Parent, childpid = 74203, selfpid = 74178, ppid = 73479
I am a Child, pid = 74203, ppid = 74178
End ...
End ...
如果子进程不及时退出for循环,子进程也会生成子进程,程序执行完不单单是生成5个子进程了。
3. 进程间共享
物理内存共享模式:读时共享,写时复制。
-
进程共享验证程序 int main()
{
printf("Begin ..\n");
int var = 100;
pid_t pid = fork();
if (pid == 0) {
printf("I am a Child, var = %d, pid = %d, ppid = %d \n",
var, getpid(), getppid());
var = 0;
printf("I am a Child, var = %d, pid = %d, ppid = %d \n",
var, getpid(), getppid());
} else if (pid > 0) {
sleep(3);
printf("I am a Parent, var = %d, childpid = %d, selfpid = %d, \
ppid = %d \n", var, pid, getpid(), getppid());
}
printf("End ...\n");
return 0;
}
-
输出结果: Begin ..
I am a Child, var = 100, pid = 74447, ppid = 74446
I am a Child, var = 0, pid = 74447, ppid = 74446
End ...
I am a Parent, var = 100, childpid = 74447, selfpid = 74446, ppid = 73479
End ...
4. execl函数族
-
execl函数的作用: fork创建子进程后执行和父进程相同的程序,子进程可以调用execl函数执行另一个程序。当一个进程调用execl函数时,该进程的用户空间代码和数据完成被新程序替换,从新程序的启动例程开始执行。 -
常用的execl函数 int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
execl 执行其它程序 execlp 执行其它程序时,使用PATH变量,执行的程序可以不用加路径 ? file 要执行的程序 ? arg 参数列表,最后一个参数以NULL结尾 ? 返回值,只有失败才返回 -
程序demo int main()
{
execlp("ls", "ls", "-l", "--color=auto", NULL);
perror("exec err");
return 0;
}
注:第二个 “ls” 是一个无用的参数占位符
5. 孤儿进程与僵尸进程
孤儿进程:父进程死了,子进程被init进程领养 僵尸进程:子进程死了,父进程没有回收子进程的资源(PCB) 如何回收僵尸进程:杀死父进程
-
孤儿进程demo #include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Begin ..\n");
pid_t pid = fork();
if (pid < 0) {
perror("fork err\n");
exit(1);
}
if (pid == 0) {
printf("I am a Child, pid = %d, ppid = %d \n", getpid(), getppid());
sleep(5);
} else if (pid > 0) {
printf("I am a Parent, childpid = %d, selfpid = %d, ppid = %d \n",
pid, getpid(), getppid());
}
printf("End ...\n");
return 0;
}
-
输出结果 Begin ..
I am a Parent, childpid = 74966, selfpid = 74965, ppid = 73479
End ...
[zhpng@iZuf6ddpzz3ipktm5kj01cZ webserver]$ I am a Child, pid = 74966, ppid = 1
End ...
6. 子进程回收
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
wait函数回收子进程,查看子进程的死亡原因。
-
作用 阻塞等待 回收子进程资源 查看子进程死亡原因 -
pid_t wait(int *status) status 出参,死亡原因 返回值 ?成功 返回终止的子进程ID ?失败 返回 -1 -
子进程死亡原因 正常死亡:WIFEXITED,如果WIFEXITED为真,使用WEXITSTATUS得到退出状态 非正常死亡:WIFSIGNALED,如果WIFSIGNALED为真,使用WEXITSTATUS得到信号 -
wait函数回收多个子进程demo #include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
printf("Begin ..\n");
int i = 0;
pid_t pid;
for (i = 0; i < 5; i++) {
pid = fork();
if (pid == 0) {
printf("I am child, pid = %d \n", getpid());
break;
}
}
sleep(i);
if (i == 5) {
for (i = 0; i < 5; i++) {
pid_t wpid = wait(NULL);
printf("wpid = %d \n", wpid);
sleep(1);
}
sleep(1);
}
printf("End ...\n");
return 0;
}
-
输出结果 Begin ..
I am child, pid = 76074
I am child, pid = 76075
I am child, pid = 76071
I am child, pid = 76072
I am child, pid = 76073
End ...
End ...
End ...
End ...
End ...
wpid = 76071
wpid = 76072
wpid = 76073
wpid = 76074
wpid = 76075
End ...
|