02_fork和vfork的使用

#include <sys/types.h>
#include <unistd.h>

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

#include <signal.h>
#include <errno.h>
#include <signal.h>

/*
1、对于数组,必须有能够自己结束的标志
2、数组作为函数参数退化为指针
{
    "aaaa",
    "bbbb"
     null 0 \0  是一样的
    }
*/

/*
    1)在fork还没实现copy on write之前。Unix设计者很关心fork之后立刻执行exec所造成的
        地址空间浪费,所以引入了vfork系统调用。
    2)vfork有个限制,子进程必须立刻执行_exit或者exec函数。
        即使fork实现了copy on write,效率也没有vfork高,但是我们不推荐使用vfork,因为
        几乎每一个vfork的实现,都或多或少存在一定的问题。

    结论:
    1:fork子进程 拷贝 父进程的数据段
          Vfork子进程与父进程 共享 数据段;
    2:fork父、子进程的执行次序不确定
         Vfork:子进程先运行,父进程后运行;

    3、Vfork和exec函数族在一起
    execve替换进程映像(加载程序)注意execve是一个系统调用;
    替换意味着:代码段、数据段、堆栈段、进程控制块PCB全部替换。


    vfork 一个进程,将另外一个应用加载起来,这个应用替换这个进程的
    代码段、数据段、堆栈段、 进程控制块.
*/

/*
    vfork有个限制,子进程必须立刻执行_exit或者exec函数,否则会出现段错误
*/
#if 0
int test(void )
{
    pid_t pid;
    int ret = 0;

    printf("befor fork pid:%d \n", getpid());
    int abc = 10;
    pid = vfork(); //errno
    if (pid == -1)  
    {
        perror("tile");
        return -1;
    }
    if (pid > 0)
    {   
        printf("parent: pid:%d \n", getpid());
    }
    else if (pid == 0)
    {
        printf("child: %d, parent: %d \n", getpid(), getppid());        
        //exit(0);// 注释掉
    }

    printf("fork after....\n");
    return 0;
}
/*
    结果
    hzmct@U-64:/study/linuxtest/day01/01process$ ./dm06_vfork
    befor fork pid:4534 
    child: 4535, parent: 4534   //说明使用vfork,子进程与父进程的pid不同
    fork after....
    parent: pid:4534 
    fork after....
    dm06_vfork: cxa_atexit.c:100: __new_exitfn: Assertion `l != NULL' failed.
    Aborted (core dumped)
*/
#endif

#if 0
int test(void )
{
    pid_t pid;
    int ret = 0;

    printf("befor fork pid:%d \n", getpid());
    pid = vfork(); //errno
    if (pid == -1)  
    {
        perror("tile");
        return -1;
    }
    if (pid > 0)
    {   
        printf("parent: pid:%d \n", getpid());
    }
    else if (pid == 0)
    {
        printf("child: %d, parent: %d \n", getpid(), getppid());    
        //把自己写应用程序启动起来
        ret =  execve("./hello", NULL, NULL);//必须以NULL结束 vim查看函数的使用 shift + k
        if (ret == -1)
          {
                perror("execve:");
          }
        printf("execve 测试有没有执行\n"); 
            exit(0);//一旦execve()函数执行错误,也要正确退出,否则会引起段错误
        }

    printf("fork after....\n");
    return 0;
}
#endif


#if 1
int test(void )
{
    pid_t pid;
    int ret = 0;

    printf("befor fork pid:%d \n", getpid());
    int abc = 10;
    //共享 父进程的数据段
    pid = vfork(); //errno
    if (pid == -1)  
    {
        //printf("pid < 0 err.\n");
        perror("tile");
        return -1;
    }
    if (pid > 0)
    {
        printf("parent: pid:%d \n", getpid());

    }
    else if (pid == 0)
    {
        printf("child: %d, parent: %d \n", getpid(), getppid());
        //printf("abc:%d\n", abc);
        //通过一个应用程序执行命令
        char *const argv[] = {"ls", "-l", NULL};
      ret =  execve("/bin/ls", argv, NULL);
      if (ret == -1)
        {
            perror("execve");
        }

      printf("execve 测试有没有执行\n");

        exit(0);
    }

    //printf("fork after....\n");
    return 0;
}
#endif

int  main()
{
    test();
    return 0;   
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
fork和vfork是两个在操作系统中常见的系统调用函数,它们用于创建新的进程。它们之间的主要区别在于父进程和子进程之间的共享资源和执行顺序。 1. fork函数: - fork函数通过复制父进程的地址空间创建一个新的子进程。父进程和子进程之间共享文件描述符、内存映射等资源,但是每个进程有自己独立的副本。 - 子进程是父进程的副本,从fork函数调用的位置开始执行,父进程和子进程的执行顺序是不确定的,取决于操作系统的调度策略。 - 子进程会继承父进程的打开文件、信号处理器、当前工作目录等状态。 - fork函数返回两次,父进程中返回子进程的ID,子进程中返回0。 2. vfork函数: - vfork函数也是通过复制父进程的地址空间创建一个新的子进程,但是与fork不同,vfork直接共享父进程的地址空间。 - 子进程共享父进程的数据段、堆栈段等资源,但是不共享代码段。子进程在执行exec或者_exit后会替换父进程的地址空间。 - 子进程必须在调用exec或者_exit之前终止或者执行另一个程序,否则可能导致父进程和子进程之间的资源冲突。 - vfork函数返回子进程的ID,与fork函数不同的是,vfork函数不会返回两次。 总结: - fork函数创建子进程时,父进程和子进程之间共享资源但具有各自独立的副本。子进程可以在任何时间执行,父进程和子进程的执行顺序不确定。 - vfork函数创建子进程时,子进程共享父进程的地址空间,但是不共享代码段。子进程必须在exec或者_exit之前终止或者执行另一个程序。 - 在使用fork和vfork时,需要根据具体的需求和场景选择合适的函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值