Linux之进程创建

        》进程创建要用到两个函数,我们先来分析第一个fork()函数

        pid_t  fork(void)      :一个现有进程可以通过调用fork()函数来创建一个他的子进程

       返回值:有两个返回值,子进程返回0,父进程返回子进程的ID

       父子进程不共享数据空间,堆,栈等 部分的地址空间内容,他们只共享正文(代码部分)。由于fork()之后经常会交给exec,所以子进程运用了“写时拷贝”方法,并不将父进程所有不可共享部分拷贝一份,而是内核将不可共享部分修改为可读,父子进程任一想修改这些区域,内核只为修改部分的那快内存复制一份。

       下面的程序演示了fork函数,从中可以看出⼦子进程对变量所作的改变并不去影响父进程中该变量的值。

       

#include <unistd.h>
#include <stdio.h>
int glob = 6; /* externalvariable in initialized data */
char buf[] = "a write to stdout\n";
int
main(void)
{
int var; /* automatic variable on the stack */
pid_t pid;
var = 88;
if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
perror("write error");
printf("before fork\n"); /* we don't flush stdout */
if ((pid = fork()) < 0) {
perror("fork error");
}else if (pid == 0) { /* child */
glob++; /* modifyvariables */
var++;
}else {
sleep(2); /* parent*/
}
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob,var);
exit(0);
}
执行及输出结果:
awrite to stdout
beforefork
pid= 2755, glob = 7, var = 89
pid= 2754, glob = 6, var = 88
wanglina@ubuntu:~/user/apue.2e$./a.out > temp.out
wanglina@ubuntu:~/user/apue.2e$cat temp.out
awrite to stdout
beforefork
pid= 2758, glob = 7, var = 89
beforefork
pid= 2757, glob = 6, var = 88
      从上面执行结果可以看出:在fork之前我们写了一句话到标准输出,由于标准输出到终端设备是行缓冲,所以遇到\n是标准输出的缓冲区内容被刷新出来了,接着创建子进程,由结果也可以看出父子进程是私有数据区域的。

      由于重定向到temp.out文件本身write一系列系统调用函数是没有缓冲区的,缓冲区是由标准I/O提供的,因为重定向所以他是全缓冲,在缓冲区里的buf字符串并没有被刷新出来,紧接着很快就创建了子进程,子进程复制了此缓冲区,于是父子进程都有了标准I/O缓冲区,所以在执行时就会printf了两句buf内容。

     总结就是:write函数是没有缓冲区的,缓冲区是由标准库来提供的,标准输出到终端设备即为行缓冲,否则为全缓冲。

》在fork之后处理的文件描述符有两种常见的情况:
1. 父进程等待子进程完成。在这种情况下,父进程无需对其描述符做任何处理。当子进程终止后,子进程对文件偏移量的修改已执行的更新。
2. 父子进程各自执行不同的程序段。这种情况下,在fork之后,父子进程各自关闭他们不需要使用的文件描述符,这样就不会干扰对方使用文件描述符。这种方法在网络服务进程中经常使用。
》父子进程之间的区别:

1. fork的返回值
2. 进程ID不同
3. 具有不同的父进程ID
4. 子进程的tms_utime、tms_stime、tms_cutime及tms_ustime均被设置为0
5. 父进程设置的⽂文件锁不会被⼦子进程继承
6. 子进程的未处理闹钟被清除
7. 子进程的未处理信号集被设置为空集

》vfork函数

    $他和fork都是创建一个子进程,但是它不复制父进程的地址空间,fork完后直接调用exec,在调用exec或者exit之前与父进程共用一个的地址空间,所以他可能会改变父进程的数据段,堆,栈;

    $vfork保证子进程先运行,在子进程调用exec或exit之后父进程才运行;

  

 #include<stdio.h>                                                           
  2 #include<string.h>
  3 #include<unistd.h>
  4 #include<stdlib.h>
  5 
  6 void fun()
  7 {
  8    printf("child exit\n");
  9 }
 10 
 11 
 12 int main()
 13 {   int g_val=0;
 14     pid_t id;
 15     id=vfork();
 16     if(id<0)
 17     {   
 18         printf("vfork fail\n");
 19         exit(1);
 20     }
 21     else if(id==0)
 22     {
 23         atexit(fun);
 24         g_val++;
 25         printf("this is child process:g_val=%d\n",g_val);
 26         sleep(3);
 27         exit(0);
 28     }
 29     else
 30     {
 31         printf("this is father process\n");
 32         printf("father is exit:g_val=%d\n",g_val);
 33     }
 34     return 0;
 35 }          
结果:

this is child process:g_val=1
child exit
this is father process
father is exit:g_val=1
从结果看出子进程修改的就是父进程里的变量,并且父进程也是在子进程exit之后才运行的。

     结束!




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值