fork 可以在 linux 中创建子进程。先看 man 手册里面的东西:
SYNOPSIS
#include
pid_t fork(void);
DESCRIPTION
fork() creates a new process by duplicating the calling process. The
new process, referred to as the child, is an exact duplicate of the
calling process, referred to as the parent ......
RETURN VALUE
On success, the PID of the child process is returned in the parent, and
0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
函数的作用的创建一个进程,这个函数会返回两次,可能有三种不同的返回值。
1. 出错返回 - 1
2. 返回 0,表示是子进程
3. 返回大于 0,表示是父进程下面的一个简单的实例:
- #include<stdio.h>
- #include<unistd.h>
- #include<signal.h>
- #include<sys/types.h>
- #include<sys/wait.h>
- #define CHILDCOUNT 1
- int main()
- {
- pid_t fpid[CHILDCOUNT ];
- int i = 0;
- for(i = 0; i < CHILDCOUNT; i++)
- {
- fpid[i] = fork();
- if(fpid[i] < 0)
- {
- perror("fork");
- return -1;
- }
- else if(fpid[i] == 0)
- {
- printf("This is child process, id:%d, my father:%d\n", getpid(), getppid());
- getchar();
- return 0;
- }
- else
- {
- printf("This is parent process, id:%d\n", getpid());
- }
- }
- getchar();
- printf("main() ------\n");
- return 0;
- }
补充一点知识
如何避免僵尸进程的出现?
如之前所说,父进程应该及时处理子进程发出来的信号,并且去获取子进程的退出码。
在父进程中使用 wait 或 waitpid 参数等待子进程退出。
也可以在收到子进程退出的信号时用 wait 或 waitpid 等待。
- #include<stdio.h>
- #include<unistd.h>
- #include<signal.h>
- #include<sys/types.h>
- #include<sys/wait.h>
- void sig_handle(int sig)
- {
- int ret = 0;
- printf("%s() +++\n", __func__);
- #if 0
- wait(NULL);
- #else
- while(ret = waitpid(-1, NULL, WNOHANG))
- {
- if(ret < 0)
- {
- printf("waitpid failed\n");
- }
- else
- {
- printf("waitpid success\n");
- break;
- }
- }
- #endif
- }
- int main()
- {
- signal(SIGCHLD, sig_handle); // 标记A
- pid_t fpid[5];
- int i = 0;
- for(i = 0; i < 5; i++)
- {
- fpid[i] = fork();
- if(fpid[i] < 0)
- {
- perror("fork");
- return -1;
- }
- else if(fpid[i] == 0)
- {
- printf("This is child process, id:%d, my father:%d\n", getpid(), getppid());
- return 0;
- }
- else
- {
- printf("This is parent process, id:%d\n", getpid());
- }
- }
- getchar();
- printf("main() ------\n");
- return 0;
- }
假如没有 signal(SIGCHLD, sig_handle); 这个语句,函数运行时,5 个子进程马上就结束了(父进程不能退出了)。这时候去查看可以看到有 5 个僵尸进程。
如下:
- xcy@xcy-virtual-machine:~/test/sock4$ ps -ef | grep test
- xcy 5573 2863 0 16:53 pts/12 00:00:00 ./test
- xcy 5574 5573 0 16:53 pts/12 00:00:00 [test] <defunct>
- xcy 5575 5573 0 16:53 pts/12 00:00:00 [test] <defunct>
- xcy 5576 5573 0 16:53 pts/12 00:00:00 [test] <defunct>
- xcy 5577 5573 0 16:53 pts/12 00:00:00 [test] <defunct>
- xcy 5578 5573 0 16:53 pts/12 00:00:00 [test] <defunct>
- xcy 5580 3126 0 16:53 pts/0 00:00:00 grep --color=auto test
- xcy@xcy-virtual-machine:~/test/sock4$
加上那句话就没有了
再来一些有意思的东西
- xcy@xcy-virtual-machine:~/test/sock4$ ps -ef | grep test
- xcy 5587 2863 0 16:57 pts/12 00:00:00 ./test
- xcy 5595 3126 0 16:57 pts/0 00:00:00 grep --color=auto test
- xcy@xcy-virtual-machine:~/test/sock4$
- #include<stdio.h>
- #include<unistd.h>
- int main()
- {
- fork();
- fork();
- fork();
- printf("+\n");
- }
这样就相当于最开始主进程创建两个进程 A 和 B。
A 又创建两个进程 A1,A2。B 又创建两个进程 B1,B2。
最后,A1,A2,B1,B2 都创建两个进程,所以最后会有 8 个进程,+ 会打印 8 次。
这样就想细胞的二次分裂一样,3 次分裂周期之后就有了 8 个细胞。
再来看个更难的:
- #include<stdio.h>
- #include<unistd.h>
- void fun()
- {
- fork();
- // fork() || fork() && fork(); // 第一个fork返回大于0,后面两个就不执行了
- fork() && fork() || fork();
- fork();
- printf("+\n");
- }
- int main()
- {
- fun2();
- }
这样一共能创建几个进程呢,+ 会打印几次呢。我们先一步一步来分析,假定所有的 fork 都会成功:
第一次分裂成 A 和 B。A 进程创建的进程和 B 创建的进程数目肯定是一样的。
就先像下面这样分析:
- fork() && fork() || fork(); // line 1
- fork(); // line 2
要注意 && 运算符和 || 运算符:
对于 && 来说:第一个表达式如果为 0,后面的表达式就不用算了
对于 || 来说:第一个表达式如果为 1,后面的表达式也不用算了。
为了更好分析,上面的 fork 一次标号为 fork1,fork2,fork3,fork4。
先看 line1。fork1 会返回一个非 0,和一个 0.
综上,第一次的 A 进程会产生 10 个进程,同理,B 也会有 10 个进程。所以一共会有 20 个进程。
来源: https://www.cnblogs.com/xcywt/p/8111314.html