1.fork函数
\qquad
执行一个可执行的程序,就创建一个进程。除此之外,还可以使用fork()函数创建一个子进程。
\qquad
fork函数的返回值有两个,本质是一个进程变成两个进程,这两个进程各自对fork做返回:返回子进程pid(父进程非负整数);返回0(子进程创建成功)。
#include<stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
printf("----------------------\n");
pid = fork();
if(pid==-1){
printf("error\n");
}
else if(pid==0){
printf("I am child,pid = %u, ppid = %lu\n",getpid(),getppid());// getpid()返回调用进程的进程ID;getppid()返回调用父级的进程ID
}
else{
printf("I am parent,pid = %u, ppid = %lu\n",getpid(),getppid());
sleep(1);
}
printf("-----------------------\n");
return 0;
}
\qquad 运行结果:
----------------------
I am parent,pid = 17257, ppid = 17200
I am child,pid = 17258, ppid = 17257
-----------------------
-----------------------
\qquad
在程序执行到pid=fork()
时,程序会创建一个子进程,
\qquad
此时父进程的pid>0
;执行
printf("I am parent,pid = %u, ppid = %lu\n",getpid(),getppid());
sleep(1);
\qquad 然后继续向下执行
printf("-----------------------\n");
\qquad
此时子进程pid=0
;执行
printf("I am child,pid = %u, ppid = %lu\n",getpid(),getppid());
\qquad 然后继续向下执行
printf("-----------------------\n");
2.循环创建子进程
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
int i;
for(i=0;i<5;i++)
{
pid = fork();
if(pid==-1){
printf("错误\n");
}
else if(pid==0){
break;
}
}
if(i<5){
sleep(i);
printf("i am %dth child,pid=%u\n",i+1,getpid());
}
else{
sleep(i);
printf("i am parent,pid=%u\n",getpid());
}
return 0;
}
3.getuid()和getgid()函数
\qquad
获取当前进程的实际用户ID:uid_t getuid(void)
\qquad
获取当前进程的有效用户ID:uid_t geteuid(void)
\qquad
获取当前进程的使用用户组ID:gid_t getgid(void)
\qquad
获取当前进程的有效用户组ID:gid_t getegid(void)
4.父子进程在fork()之后的异同
\qquad
在fork之后:
\qquad
相同点:全局变量;.data;.text;栈;堆;环境变量;用户ID;进程工作目录…
\qquad
不同点:进程ID;fork返回值;父进程ID;进程运行时间;闹钟/定时器;未决信号集
\qquad
父子遵循读时共享写时复制的原则。父子进程共享:文件描述符(打开文件的结构体);mmap建立的映射区。而父子进程执行的先后顺序,取决于内核的调度算法。