1.fork函数
\qquad执行一个可执行的程序,就创建一个进程。除此之外,还可以使用fork()函数创建一个子进程。
\qquadfork函数的返回值有两个,本质是一个进程变成两个进程,这两个进程各自对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建立的映射区。而父子进程执行的先后顺序,取决于内核的调度算法。