十、Linux系统编程-进程(三)父子进程共享文件、fork和vfork、exit和_exit、atexit注册退出事件

一、fork之后父子进程共享文件

打开的文件在fork之后共享文件表。



示例:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)
#define MAJOR(a) (int)((unsigned short)a>>8)
#define MINOR(a) (int)((unsigned short)a & 0xFF)
int filetype(struct stat *buf);
int main(int argc,char* argv[])
{
        int infd;
        int outfd;
        int ret;
        infd = open("aa.txt",O_WRONLY);
        if ((ret = fork()) > 0)
        {
                write(infd,"ABC",3);
        }
        else
        {
                write(infd,"DEF",3);
        }
        wait(&ret);
        return 0;
}
文件里会输出:ABCDEF字样。

二、fork和vfork

在fork还没实现copy on write之前。Unix设计者很关心fork之后立刻执行exec所造成的地址空间浪费,所以引入了vfork系统调用。
但是vfork有个限制,子进程必须立刻执行_exit或者exec函数。  vfork保证子进程先运行,在子进程调用exec或exit之后父进程才可能被调度运行。子进程没有自己的地址空间,在vfork()返回后子进程直接运行在父进程的栈空间,并使用父进程的内存和数据。
注意:即使fork实现了copy on write,效率也没有vfork高,但是我们不推荐使用vfork,因为 几乎每一个vfork的实现,都或多或少存在一定的问题。
示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)

int main(int argc,char* argv[])
{
        signal(SIGCHLD,SIG_IGN);
        int ret;
        int var;
        var = 1;
        if ((ret = vfork()) > 0)
        {
                printf("parent start...\n");
                printf("var=%d\n",var);
        }
        else if(ret == 0)
        {
                sleep(3);
                var = 3;
                _exit(0);
        }
        return 0;
}
父进程等待子进程执行exit或者exec,子进程改变了父进程的数据。父进程在3s之后输出:
parent start...
var=3
三、进程退出方式和atexit
正常退出
  • main函数返回
  • 调用exit
  • 调用_exit
异常退出
  • 调用abort
  • 由信号终止
exit和_exit的区别是_exit是系统调用,而exit是C库调用。exit结束之前会清空缓冲区并且调用终止处理程序,而缓冲区和终止处理程序都术语用户态,所以_exit不会清空缓冲区,也不会调用终止处理程序。


示例:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)

void my_exit1()
{
        printf("my_exit1...\n");
}
void my_exit2()
{
        printf("\nmy_exit2...\n");
}
int main(int argc,char* argv[])
{
        atexit(my_exit1);
        atexit(my_exit2);
        char ch;
        ch = getchar();
        if (ch == 'a')
        {
                printf("hello");
                exit(0);
        }
        else
        {
                printf("hello");
                _exit(0);
        }
}
输出:

sh@ubuntu:~/sys$ ./a.out 
a
hello
my_exit2...
my_exit1...
sh@ubuntu:~/sys$ ./a.out 
b
sh@ubuntu:~/sys$ 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值