zoukankan      html  css  js  c++  java
  • Linux下C语言的进程控制编程

    代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    /*************基本的函数API********************
    1-pid func
    pid_t getpid(void)
    pid_t fork(void) 
        fork函数创建的字进程是父进程的副本,执行的是与父进程完全相同的程序,为了让fork子进程能够运行另外的程序,需要用的exec函数
    
    2-exec func
    int execl(const char *path,const char *arg, ...)
    int execlp(const char *file,const char *arg, ...)
    int execle(const char *path,const char *arg, ..., char * const envp[])
    int execv(const char *path,const char *arg[])
    int execvp(const char *file,const char *arg[])
    int execve(const char *file,const char *arg, char * const envp[])
    
    3-system func
    int system(const char *string)
    **********************************************/
    #define Test_fork 0 
    #define Test1 0
    #define Test2 1
    
    #define Test_exec 1
    #define Test_syst 0
    
    static int idata = 111;
    
    int main(void)
    {
    #if Test_fork
        pid_t pid0,pid1;
        pid0 = fork();
        pid1 = fork();
        printf("Fork's PID0 = %d
    PID1 = %d
    ",pid0,pid1);
        //printf("PID = %d
    ", getpid());
    #endif
    
    #if Test1
        int istack = 222;
        pid_t childPid;
        printf("Test Fork!
    ");
        fflush(stdout);
        // The parent's printf's buffer content will be copy to child-process's buffer and being stdout to the file object but not the screen!
    
        switch(childPid = fork())
        {
                case -1: exit(0);
                case  0: idata *= 3; istack *= 3; break;
                default: sleep(3); break;
         }
    
         printf("PID=%ld %s idata=%d istack=%d 
    ",(long)getpid(),(childPid == 0)?"(child)":"(parent)",idata,istack);
         exit(EXIT_SUCCESS);
    #endif
    
    #if Test2
         pid_t pid0,pid1;
         pid0 = fork();
         printf("PID=%ld %s
    ",(long)getpid(),(pid0 == 0)?"(child0)":"(parent)");
         pid1 = fork();
         printf("PID=%ld %s
    ",(long)getpid(),(pid1 == 0)?"(child1)":"(parent)");
         exit(EXIT_SUCCESS);
    #endif
    
    
    #if Test_exec
        if(0 == fork())
        {
            int ret;
            ret = execlp("ls","ls","-l", NULL);
            return 0;
        }
    #endif
    
    #if Test_syst
        int ret;
        ret = system("ls -al");
        printf("OK!
    ");
        return 0;
    #endif
    
        return 0;
    }

    主要说明上述程序中fork的相关内容,纪录在此,方便后面理解!

    fork()函数用来创建一个新的进程,新创建的这个进程的data数据段,stack堆栈段等进程基本的内容以及当前程序状态指针PC-point也完全和父进程相同!也就是说fork创建的子进程是父进程的副本,新创建的这个进程,Linux会为它分配对应的内存页来保存与父进程完全相同data、stack、进程运行到的目前的状态。但是对于程序段text,父进程与子进程是共享的!对于Test2程序的运行结果如下所示:

    对上述的结果分析如下所示:

     如图所示,每一个fork下面只要存在fork那么就会产生多级的子进程。

    1、如图中所示的关系,P是C0的父进程,也是C1的父进程,C0是C2的父进程。

    2、在这样的关系当中,所有进程的状态都有所不同,再运行到fork0的位置处,P和C0的PC指针状态相同,C0进程不会再去运行fork0上面的所有程序,同样的C2不会运行fork1上面的所有程序,C1不会运行fork1上面的所有程序

         ,这样也就是子父进程的状态相同的意思!

    3、图中的printf表示该进程PC指针知道该位置处需要运行的任务,总共运行了6条printf,这和我们的演示结果相同,printf("PID=%ld %s ",(long)getpid(),(pid1 == 0)?"(child1)":"(parent)");

          这样的代码会帮我们区分子父进程并打印出当前进程的PID!

    4、由于所有进程包括子父进程之间都会存在竞争关系,所以运行的结果每次都会不同,同时PID的数值也会有所不同(对于多核心CPU来说,进程可能存在同步运行的情况!)。

    5、一定要注意,fork在父进程运行过程中的返回值是子进程真实的PID number,pid_t pid = fork(),这样在父进程中获取的pid是真实的进程ID>0,获取失败则为-1,但是在进入子进程之后,实际上这个值是0,

          所以一对子父进程中的pid的值不同!这很重要!

    6、子父进程之间的数据交换可以使用信号量的方式来同步和互斥!#include <singnal.h>

    7、子父进程不共享数据段,堆栈段,进程PCB内容,但是共享不可改写的代码段!所以数据的修改不是同步的!但是对于新创建的文本等字符设备上的文件对象,子父进程存在竞争关系,需要同步和互斥来保证数据的正确性!

    8、注意在Test1程序当中,我们在printf之后添加了fflush函数,对printf函数中的缓冲内容进行了刷新,在重定向到文件过程中就不会出现fork的子进程的输出缓冲内容了,不然结果会不同:

     

    9、当父进程先于子进程终止时,子进程变成了孤儿进程,操作系统统一为其找到一个 PID为 1 的 init(操作系统最先运行的进程),接管此进程。

    进程其他相关API:

    1、使用wait()函数等待子进程完成操作,或者使用waitpid()

    pid_t pid,pid_end;
    pid = fork();
    if(pid == 0)
    {
            printf("ChildProcess:%ld
    ",(long)getpid());
                    sleep(5);
    }
    else
    {
            printf("ParentProcess:%ld
    ",(long)getpid());
    }
    pid_end = wait(NULL);
    printf("The ChildProcess:PID %d is Stopped!
    ",pid_end);
    exit(EXIT_SUCCESS);

    运行结果如下所示:

  • 相关阅读:
    MySql 免安装配置
    MySql 语句优化的几个小建议
    Sharding-JDBC 公共表
    Sharding-JDBC 垂直分库
    Sharding-JDBC 水平分库
    Vuejs基础使用
    webpack配置开发环境和生产环境
    webpack常见应用
    webpack-用loader加载css样式、图片、字体、数据
    webpack核心概念-模式/loader/插件及其他
  • 原文地址:https://www.cnblogs.com/uestc-mm/p/7630161.html
Copyright © 2011-2022 走看看