17、fork函数
1、定义
#include <unistd.h>
#include<sys/types.h>
pid_t fork( void );
pid_t 是一个宏定义,其实质是int,被定义在#include<sys/types.h>中
返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
2、函数说明:
一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。File locks and pending signals are not inherited. 【3】
If the call to fork() is executed successfully, Unix will
① make two identical copies of address spaces, one for the parent and the other for the child.
② Both processes will start their execution at the next statement following the fork() call.
3、为什么fork会返回两次?
由于在复制时复制了父进程的堆栈段,所以两个进程都停留在fork函数中,等待返回。因为fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。
After a new child process is created, both processes will execute the next instruction following the fork() system call.
调用fork之后,代码有两份,都从fork函数中返回。
Please note that Unix will make an exact copy of the parent's address space and give it to the child. Therefore, the parent and child processes have separate address spaces.
示例代码1
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
int main(int argc,char**argv)
{
int pid=fork();
if(pid == -1)
{
print("error!");
}
else if(pid == 0)
{
print("This is the child process!");
}
else
{
print("This is the parent process! child process id = %d", pid);
}
return 0;
}
示例代码2
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_COUNT 200
#define BUF_SIZE 100
void main(void)
{
pid_t pid;
int i;
char buf[BUF_SIZE];
fork();
pid = getpid();
for (i = 1; i <= MAX_COUNT; i++) {
sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
write(1, buf, strlen(buf));
}
}
为什么用write,而不用printf呢?because printf() is "buffered," meaning printf() will group the output of a process together,这样,会把子进程和父进程的输出混起来。所以用use the "unbuffered" write。
示例代码3
#include <stdio.h>
#include <sys/types.h>
#define MAX_COUNT 200
void ChildProcess(void); /* child process prototype */
void ParentProcess(void); /* parent process prototype */
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
return 0;
}
void ChildProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf(" This line is from child, value = %d\n", i);
printf(" *** Child process is done ***\n");
}
void ParentProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf("This line is from parent, value = %d\n", i);
printf("*** Parent is done ***\n");
}
4、Error Codes
出错返回错误信息如下:
EAGAIN :达到进程数上限.
ENOMEM :没有足够空间给一个新进程分配.
fork()系统在Linux中的返回值是没有NULL的.
参考
【1】 http://baike.baidu.com/view/1952900.htm
【2】 http://linux.die.net/man/2/fork
【3】 不错的网页
http://www.csl.mtu.edu/cs4411/www/NOTES/process/fork/create.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· ASP.NET Core - 日志记录系统(二)
· 博客园 & 1Panel 联合终身会员上线
· 支付宝事故这事儿,凭什么又是程序员背锅?有没有可能是这样的...
· https证书一键自动续期,帮你解放90天限制
· 在 ASP.NET Core WebAPI如何实现版本控制?
· 告别虚拟机!WSL2安装配置教程!!!