fork可以在linux中创建子进程。先看man手册里面的东西:

SYNOPSIS
       #include <unistd.h>

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 = ;
for(i = ; i < CHILDCOUNT; i++)
{
fpid[i] = fork();
if(fpid[i] < )
{
perror("fork");
return -;
}
else if(fpid[i] == )
{
printf("This is child process, id:%d, my father:%d\n", getpid(), getppid());
getchar();
return ;
}
else
{
printf("This is parent process, id:%d\n", getpid());
}
} getchar();
printf("main() ------\n");
return ;
}

补充一点知识

  • fork出来的子进程复制了父进程的内存空间(处理代码区都复制了),和父进程共享代码区
  • fork之后,父子进程谁先执行不确定
  • 子进程中新定义的变量和父进程没有任何关系
  • 子进程也会复制父进程文件描述符,但是不会复制文件表。而是共用一个offset
  • 如果父进程先挂了,子进程就变成孤儿进程了,它爹就会变成1号进程
  • 子进程挂了会给父进程发信号(SIGCHLD),如果父进程收到该信号没有及时处理。子进程就变成僵尸进程了,直到父进程处理了该信号或父进程也退出了。

如何避免僵尸进程的出现?
如之前所说,父进程应该及时处理子进程发出来的信号,并且去获取子进程的退出码。 
在父进程中使用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 = ;
printf("%s() +++\n", __func__);
#if 0
wait(NULL);
#else
while(ret = waitpid(-, NULL, WNOHANG))
{
if(ret < )
{
printf("waitpid failed\n");
}
else
{
printf("waitpid success\n");
break;
}
}
#endif
} int main()
{
signal(SIGCHLD, sig_handle); // 标记A
pid_t fpid[];
int i = ;
for(i = ; i < ; i++)
{
fpid[i] = fork();
if(fpid[i] < )
{
perror("fork");
return -;
}
else if(fpid[i] == )
{
printf("This is child process, id:%d, my father:%d\n", getpid(), getppid());
return ;
}
else
{
printf("This is parent process, id:%d\n", getpid());
}
} getchar();
printf("main() ------\n");
return ;
}

假如没有signal(SIGCHLD, sig_handle);这个语句,函数运行时,5个子进程马上就结束了(父进程不能退出了)。这时候去查看可以看到有5个僵尸进程。 
如下:

xcy@xcy-virtual-machine:~/test/sock4$ ps -ef | grep test
xcy : pts/ :: ./test
xcy : pts/ :: [test] <defunct>
xcy : pts/ :: [test] <defunct>
xcy : pts/ :: [test] <defunct>
xcy : pts/ :: [test] <defunct>
xcy : pts/ :: [test] <defunct>
xcy : pts/ :: grep --color=auto test
xcy@xcy-virtual-machine:~/test/sock4$

加上那句话就没有了

xcy@xcy-virtual-machine:~/test/sock4$ ps -ef | grep test
xcy : pts/ :: ./test
xcy : pts/ :: grep --color=auto test
xcy@xcy-virtual-machine:~/test/sock4$

再来一些有意思的东西
我们知道fork会出现两个进程,两个进程都会往下执行,看下面的代码:

#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.

  • 1.返回0,则直接进入line2,fork4创建两个进程
  • 2.返回大于0,执行fork2。
  • 2.1 fork2返回0,则需要执行fork3,再接着执行fork4.这里会创建4个进程
  • 2.2 fork2返回大于0,也会执行fork3和fork4。相当于也创建4个进程。

综上,第一次的A进程会产生10个进程,同理,B也会有10个进程。所以一共会有20个进程。

关于signal和fork的思考的更多相关文章

  1. 12.详解Condition的await和signal等待通知机制

    1.Condition简介 任何一个java对象都天然继承于Object类,在线程间实现通信的往往会应用到Object的几个方法,比如wait(),wait(long timeout),wait(lo ...

  2. linux signal函数遇到的问题

    1.关于signal函数的定义 signal最开始的原型是这: void (*signal(int signo, void (*func)(int)))(int);看过下面两行,了解到上面这一行是这个 ...

  3. 详解Condition的await和signal等待/通知机制

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  4. Linux Pthread 深入解析(转-度娘818)

    Linux Pthread 深入解析   Outline - 1.线程特点 - 2.pthread创建 - 3.pthread终止         - 4.mutex互斥量使用框架         - ...

  5. Network client/server

    <Beginning Linux Programming_4th>  chapter 15 Sockets 1  A simple local client/server 1)  clie ...

  6. 关于synchronized和lock 的使用及其在线程间的通信

    题目要求:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次 synchronized的使用 import java.util.conc ...

  7. GDB常用命令使用说明(一)

    本文由霸气的菠萝原创,转载请注明出处:http://www.cnblogs.com/xsln/p/gdb_instructions1.html 全部关于gdb的文章索引请点这里 GDB(GNU Deb ...

  8. 玩转Nodejs的集群

    在Nodejs中使用集群还是不容易的.Javascript的单线程属性让nodejs下的应用很难使用现代机器的多核特性.比如下面的代码实现了一个http服务器的主干部分.这部分代码只会执行在一个线程上 ...

  9. 浅谈NodeJS多进程服务架构基本原理

    阅读目录 一:nodejs进程进化及多进程架构原理 二:node中child_process模块实现多进程 三:父子进程间如何通信? 四:理解cluster集群 回到顶部 一:nodejs进程进化及多 ...

随机推荐

  1. 经典面试题: 从输入URL到页面加载的过程发生了什么?

    可以分为这几个大的过程: DNS解析 TCP连接 客户端发送HTTP请求 服务器处理请求并返回HTTP报文 浏览器解析渲染页面 结束 其中(1)DNS解析可以理解为主寻找这个IP地址的过程,其中如果找 ...

  2. WebService--jax

    使用javax.jws编写webservice服务: 服务端: 1,定义webservice接口: package com.jws.serviceInterface; import javax.jws ...

  3. C++雾中风景1:友元类与面向对象

    因为后续准备入职的公司都希望能转C++,所以最近也是按部就班的开始进行C++的学习.然后这个系列的文章打算探究C++的语言特性,也比较一下不同语言(如Java,Scala,Python,Go)之间的设 ...

  4. ASP.NET没有魔法——ASP.NET Identity与授权

    一个完整的ASP.NET的请求中会存在身份验证(Authentication)阶段以及授权(Authorization)阶段,英文单词Authentication和Authorization非常相似, ...

  5. Nodejs前端服务器压缩图片

    Nodejs作为前端服务器,自然能承担处理图片的能力, 使用GM for nodejs 作为图片处理器,调用ImageMagick处理图片 使用ImageMagick var imageMagick ...

  6. 程序、计算机程序、java初论

    一.程序? 程序一词来自生活,通常指完成某些事情的一种既定方式和过程,可以将程序看成对一系列动作的执行过程的描述. 例如:个人去银行取钱 1.带上存折/银行卡去银行 2.取号排队 3.将存折或储蓄卡递 ...

  7. P2915 [USACO08NOV]奶牛混合起来Mixed Up Cows

    题目描述 约翰家有N头奶牛,第i头奶牛的编号是Si,每头奶牛的编号都是唯一的.这些奶牛最近 在闹脾气,为表达不满的情绪,她们在挤奶的时候一定要排成混乱的队伍.在一只混乱的队 伍中,相邻奶牛的编号之差均 ...

  8. mysql数据库的安装与基本配置

    目录 绿色版下载 mysql绿色版(5.7版本的安装与配置) 绿色版下载: mysql官网下载地址:https://www.oracle.com/index.html mysql绿色版(5.7版本的安 ...

  9. weex 环境搭建

    最近为了项目需要(实际上是为了年底KPI),领导要求用3天时间,学习并使用weex开发一个页面,说实话,压力山大.在这之前压根儿就没听说过啊,一脸懵逼 无奈之余只能Google了,惊喜的发现weex的 ...

  10. 【前端开发】--js弹框

    js三种弹框 一.普通弹框 这类弹框就是仅仅是个提示作用,并不会做其它操作 关键词:alert()    这个没啥好说的,就是一个弹框.  二.判断弹框     这类框有一个判断作用 关键字:conf ...