zoukankan      html  css  js  c++  java
  • UNIX环境高级编程第8章进程控制 8.3fork 文件共享 vfork

    %H]1)K)(G[IRIQ0VLVRRGPQ

    进程ID为0的进程通常是调度进程,常常被称为交换进程swapper,该进程是内核的一部分,这并不执行任何磁盘上的程序,因此也被称为系统进程,进程ID为1是init进程,在自举过程结束时由内核调用,该进程的程序文件为/etc/init或者/sbin/init,此进程负责在自举内核后启动一个UNIX系统。init通常读取与系统相关的初始化文件/etc/rc*文件,或/etc/inittab文件,以及/etc/init.d中的文件。并将系统引导到一个状态(例如多用户)。init决不会终止,它是一个普通的用户进程(与交换进程不同,它不是内核中的系统进程),但是它以超级用户运行,它是所有孤儿进程的父进程。

    进程ID2是页守护进程pagedaemon,负责支持虚拟存储系统的分页操作。

    BC[C]TS`7DSGT_7(]C)W22X

    AISI`7`N@G6ZB]3OZB~B%CG

    O81DVT6TM(MZC89]M_IZA2S

    Q_6P%{LAEZ%H2T`50Y_XM[2

    一个现有进程可能通过调用fork创建一个新进程,新进程称为子进程,fork函数调用一次返回两次,再次返回的唯一区别是,子进程返回值是0,父进程的返回值是子进程ID。

    子父进程继续执行fork调用之后的指令。子进程是父进程的副本,子获得父进程数据空间,堆和栈的副本。子父并不共享,因为子复制了父的这些存储空间。父子共享正文段。

    //以下来自网络

    对于exec系列函数
        一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另一个程序了。不过exec类函数中有的还允许继承环境变量之类的信息,这个通过exec系列函数中的一部分函数的参数可以得到

    对于exec():
    1、进程调用exec()后,将在同一块进程内存里用一个新程序来代替调用
      exec()的那个进程,新程序代替当前进程映像,当前进程的“数据段”,
    “堆栈段”和“代码段”背新程序改写。
    2、新程序会保持调用exec()进程的ID不变。
    3、调用exec()之前打开打开的描述字继续打开(好像有什么参数可以令打开
      的描述字在新程序中关闭)

    //以上来自网络

    // proc/fork1.c 8-1
    #include "apue.h"
    
    int glob = 6; /* external variable in initialized data */
    char buf[] = "a write to stdout
    ";
    
    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)
            err_sys("write error");
        printf("before fork
    
    "); /* we don't flush stdout */
        /* fflush(stdout); */           /* if comments this line, the child will flush the stdout */
    
        if ((pid = fork()) < 0)
        {
            err_sys("fork error");
        }
        else if (pid == 0)
        {
                                                  /* child, first flush buffer */
            printf("hello, I am child process
    ");
            glob++;                               /* modify variables */
            var++;
        }
        else
        {
            sleep(3);                             /* parent */
            printf("hello, I am parent process
    ");
        }
    
        if (0 == pid) /* for the child process, variable pid is 0 */
        {
            printf("hello, I am child process, variable pid is 0
    ");
        }
        else          /* for the parent process, variable pid is child pid */
        {
            printf("hello, I am parent process, variable pid is child pid
    ");
        }
        printf("pid = %d, pid = %d, glob = %d, var = %d
    
    
    ", pid, getpid(), glob, var);
    
        return 0;
    }
    
    all: shell1 shell2 fork1
    shell1: shell1.c
    	g++ -g -Wall shell1.c ../lib/libapue.a -I ../include -o shell1
    shell2: shell2.c
    	g++ -g -Wall shell2.c ../lib/libapue.a -I ../include -o shell2
    fork1: fork1.c
    	g++ -g -Wall fork1.c ../lib/libapue.a -I ../include -o fork1
    clean:
    	rm shell1 shell2 fork1
    

    image

    交互式的方式执行fork1,在子进程创建之前,before fork已经被父进程从缓冲区刷新,before fork已经被输出到终端设备(交互式是行缓冲),而采用重定向到磁盘文件的方式,这种情况是全缓冲的,也就是说,before fork还在缓冲区,这个缓冲区又被复制到了子进程,于是子进程缓冲区被刷新时,before fork在子进程终止时,被输出了出来。

    在重定向父进程的标准输出时,子进程的标准输出同样被重定向,这点还是有疑惑

    JL$PZOR9~3N$`Z6SC`6B(5X

    CON274UC~$$Z{3W)QLBJ(4L

    RWRYTCPV5CU]KV{}H~UW`BC

    H9JF[)E5K5A%HK8`1VKI9FM

    A7F~37(Y)67%OETXUMG22L9

    1VMN9[GZ%%7XV{AO{%2WD_G

    vfork用于创建一个新进程,该进程的目的是exec一个新进程,但是它不将父进程的地址空间完全复制到子程序,因为子会立即调用exec,或者exit,于是也就不会访问该地址空间,在调用exec之前,子在父进程的空间运行,且vfork保证子进程先运行,在子调用exec或exit之后,父才可能被调度运行。

    // proc/vfork1.c 8-2
    #include "apue.h"
    
    int glob = 6; /* external variable in initialized data */
    
    int main(void)
    {
        int var; /* automatic variable on the stack */
        pid_t pid;
    
        var = 88;
        printf("before vfork
    "); /* we don't flush stdio */
        if ((pid = vfork()) < 0) 
        {
            err_sys("vfork error");
        }
        else if (pid == 0)
        {   /* child */
            // vfork ensure the child will go first, parent will not continue untill the child run function exec or exit, no matter how long the parent has to wait
            glob++; /* modify parent's variables */
            var++;
            printf("I'm child, I am going to sleep 5 second
    ");
            sleep(5);
            printf("I'm child, I am going to invork exit function
    ");
            _exit(0); /* child terminates */
        }
    
        /*
         * Parent continues here.
         */
        printf("parent print: pid = %d, glob = %d, var = %d
    ", getpid(), glob, var);
        return 0;
    }
    
    all: shell1 shell2 fork1 vfork1
    shell1: shell1.c
    	g++ -g -Wall shell1.c ../lib/libapue.a -I ../include -o shell1
    shell2: shell2.c
    	g++ -g -Wall shell2.c ../lib/libapue.a -I ../include -o shell2
    fork1: fork1.c
    	g++ -g -Wall fork1.c ../lib/libapue.a -I ../include -o fork1
    vfork1: vfork1.c
    	g++ -g -Wall vfork1.c ../lib/libapue.a -I ../include -o vfork1
    clean:
    	rm shell1 shell2 fork1 vfork1

    OH@[C{}75S8E(ETAED)YPA3

    %M@%EX{I7KJ[N1%6ZUZ{292

    V]]R_EM0`X9~HND{RO3~EI0

    @GD}UZC1NB7WWX8N@VRN_~L

    bf6c75b6a68ac3d3b78126e1528bbaac

  • 相关阅读:
    C#事务相关
    建造者模式
    CUPS/Printer sharing
    vim note write
    linux下神奇的script
    Nginx server之Nginx添加ssl支持
    nginx使用ssl模块配置HTTPS支持
    stardict dict url
    收银台(POSBox) 配置向导
    让 Odoo POS 支持廉价小票打印机
  • 原文地址:https://www.cnblogs.com/sunyongjie1984/p/4262769.html
Copyright © 2011-2022 走看看