函数原型
pid_t fork(void);失败返回-1;成功返回:① 父进程返回子进程的 ID(非负) ②子进程返回 0
pid_t getpid(void);获取当前进程 ID
pid_t getppid(void);获取当前进程的父进程 ID
fork函数
创建一个子进程。
pid_t fork(void);失败返回-1;成功返回:① 父进程返回子进程的ID(非负)②子进程返回 0
pid_t类型表示进程ID,但为了表示-1,它是有符号整型。(0不是有效进程ID,init最小,为1)
注意返回值,不是fork函数能返回两个值,而是fork后,fork函数变为两个,父子需【各自】返回一个。
getpid函数
获取当前进程ID
pid_t getpid(void);
getppid函数
获取当前进程的父进程ID
pid_tgetppid(void);
案例一 打印父子进程id
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h>
int main()
{
pid_t pid ;
pid = fork();
if(pid<0)
{
perror("fork error");
}
else if(pid==0)
{
printf("I am child pid =%d my father pid=%d\n",getpid(),getppid());
}
else
{
printf("I am father pid =%d my father pid =%d\n",getpid(),getppid());
}
return 0;
}
案例二 顺序打印5个进程
练习:通过命令行参数指定创建进程的个数,每个进程休眠1S打印自己是第几个被创建的进程。如:第1个子进程休眠0秒打印:“我是第1个子进程”;第2个进程休眠1秒打印:“我是第2个子进程”;第3个进程休眠2秒打印:“我是第3个子进程”。
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h>
int main()
{
pid_t pid;
int i;
for(i=0;i<5;i++)
{
pid =fork();
if(pid==0)
{
break;
}
}
if(5==i)//父进程 等待for结束自己台跳出
{
sleep(5);
printf("I am father\n");
}
else//子进程 提前break跳出 打印
{
sleep(i);
printf("I am %d child \n",i+1);
}
return 0;
}
父子进程间遵循读时共享写时复制的原则
相同部分:全局变量、.data、.text、栈、堆、环境变量、用户 ID、宿主目录、进程工
作目录、信号处理方式…
不同部分:1.进程 ID 2.fork 返回值 3.父进程 ID 4.进程运行时间 5.闹钟(定时器) 6.未决信号集
重点注意!躲避父子进程共享全局变量的知识误区!
【重点】:
父子进程共享:1. 文件描述符(打开文件的结构体)
2. mmap建立的映射区 (进程间通信详解)
特别的,fork之后父进程先执行还是子进程先执行不确定。取决于内核所使用的调度算法。