进程
pid_t fork(void);
功能:创建一个新的进程
参数:无
返回值:
成功:如果是父进程返回子进程的pid号;如果是子进程返回0;
失败:返回-1
特点一:调用一次,返回两次
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
pid_t pid;
if( (pid = fork()) < 0)
{
perror("fork error");
exit(1);
}
else if(pid == 0)
{
printf("im child process\n");
}
else if(pid > 0)
{
waitpid(pid, NULL, 0);
printf("im farther process\n");
}
printf("this is a fork fuction, pid = %d\n", pid);
return 0;
}
编译运行(如下图):
第一个“this is a fork fuction,pid = 0”是子进程打印的;
第二个“this is a fork fuction,pid = 3089”是父进程打印的;
why?
因为以阻塞的方式调用了waitpid函数,所以父进程在waitpid这一直处于阻塞等待,直到子进程退出才继续往下执行(看看pid的值);
特点二:子进程执行的位置
子进程是父进程的副本,它将获得父进程数据空间、堆、栈、缓冲区等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
pid_t pid;
printf("this is a fork fuction\n");
if( (pid = fork()) < 0)
{
perror("fork error");
exit(1);
}
else if(pid == 0)
{
printf("im child process\n");
}
else if(pid > 0)
{
waitpid(pid, NULL, 0);
printf("im farther process\n");
}
printf("hello world, pid = %d\n", pid);
return 0;
}
看看进程的执行特点:程序从fork处开始分裂成两个进程,两个进程拥有相同的代码段、缓冲区等,但是子进程是从fork后边开始执行的,所以上边的程序只会执行一次“this is a fork fuction”,是父进程执行的,子进程是不执行这里的代码的,但是这里也被它复制过去了;
程序编译执行(如下图):
特点三:复制缓冲区
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
pid_t pid;
//注意,将这里的\n去掉了,此时,行缓存不会刷新
printf("this is a fork fuction");
if( (pid = fork()) < 0)
{
perror("fork error");
exit(1);
}
else if(pid == 0)
{
printf("***im child process\n");
}
else if(pid > 0)
{
waitpid(pid, NULL, 0);
printf("***im farther process\n");
}
return 0;
}
编译执行(如下图):
“this is a fork function”将\n去掉后,没有刷新行缓存,直到子进程中遇到了\n,刷新了行缓存,直接连原来缓冲区中的这一句与子进程中的语句一起打印了出来;
由于父子进程拥有相同的代码,只是执行的位置不一样,所以父进程遇见\n同样连同原来的语句一同打印出来;
知识点穿插:
行缓存刷新的条件?
这里强调一下,只有正常退出才会刷新缓存:
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("hello world");
while(1)
;
return 0;
}
编译执行:
行缓存没有被写满(行缓存1k,这几个字符不够),没有遇见\n,所以,程序执行时会一直进行死循环;
现在用kill -9 来杀死它,这属于非正常退出了,看看缓存区刷不刷新?
看到了吧,hello world没有打印出来,说明行缓存没有刷新。