zoukankan      html  css  js  c++  java
  • Linux_ fork 进程操作

    1. 什么是进程

      程序的运行实例,就是“进程”
      一个程序,同时执行多次,则产生多个不同的进程。

      程序是静态的
      进程是动态的

    2. 进程的结构
      进程的组成:程序代码、数据、变量、文件描述符(表示已打开的文件)、环境等组成。

      每个进程有一个唯一的编号,称为”进程标识符”(PID)
      PID >= 2
      PID=1的进程是init进程。

      进程之间共享程序代码
      即,同一个程序的多个进程,共享一个代码拷贝。

      进程之间共享函数库。

      进程有自己的”栈空间”、“程序计数器”、变量。

    3. 进程表
      Linux把所有进程的相关信息放在一个表中,称为进程表
      每个进程是一个表项。
      进程表的索引,是PID

      可同时运行的进程数取决于该进程表的容量。

    4. 进程的查看
      ps 显示与该终端连接的进程。
      ps -ef
      ps ax

    5. 进程的状态
      ps ax
      ps的stat列表示进程的状态:
      S: 睡眠,即“挂起”,等待某个事件的发生。
      R: 运行
      D: 不可中断的睡眠
      T: 停止
      Z: 死进程(僵尸进程)
      s: 进程是会话期的首进程。
      +:进程属于前台进程

    6. 进程的调度
      单处理器上,同一个时刻只能有一个进程运行。
      Linux内核用“进程调度器”来决定下一个时间片执行哪个进程。

    7. 进程的启动
      1)system
      实例:main7.c

      在程序的内部,创建一个新进程,执行指定的shell命令。
      
      主进程将等待新进程执行结束后,才能继续执行。
      除非新进程以后台方式运行,system("ls &") 
      
      效率不高,因为要先启动shell, 然后再运行指定的shell命令。
      

      2) exec (进程替换)
      exec指一组函数.
      用于:从当前进程切换到另一个程序执行,且不返回到原来的程序(除非发生了错误,返回-1)。

      "l"组 (l即list, 新程序的参数为列表形式,即可变参数列表)
      execl
      execlp
      execle
      
      “v"组(v即vector, 新程序的参数为数组形式, 参数个数不变
      execv
      execvp
      execve
      
      p后缀:
      第一个参数是要执行的文件名,不含路径。
      文件的路径由系统默认的环境变量(path)指定。
      
      e后缀:
      最后一个参数是字符串数组,表示指定的环境变量。
      注意,这个环境变量是指程序替换以后,
            新程序运行期间的环境变量。
        而不是替换新程序时的环境变量,
        所以execle函数的第一个参数仍然需要使用路径。
        替换到新程序以后,此时的环境就是execle的最后一个参数。
      
      实例:main8.c
      分别用以上六种形式,创建"ls -l"进程。
      
      注意:
      exec启动的新进程继承原进程的很多特性:
      比如,原进程中打开的文件描述符,在新进程中仍保持打开。
      

      3) fork (进程复制)
      复制的新进程(子进程),与原进程一模一样,
      但有自己的数据空间、环境、文件描述符等。

       fork的返回值
       在原进程(父进程)中,fork返回新进程(子进程)的PID
       在新进程(子进程)中,fork返回0
       fork失败,返回-1
             失败原因:父进程能拥有的子进程数超出限制(CHILD_MAX)
                            进程表中的空间不足
                            虚拟内存不足
      

      实例:main9.c

    8. 等待子进程结束
      1) wait
      功能:父进程等待任意它的任一个子进程结束
      返回该结束子进程的PID
      参数: 实参非空时,返回子进程的退出状态。
      参见man 2 wait

      实例:main10.c

      2) waitpid
      功能:父进程等待指定的子进程。
      参数:
      详见man 2 waitpid
      参数3常使用WNOHANG(不阻塞,立即返回)
      实例:
      waitpid(child_pid, (int*)0, WNOHANG);
      如果子进程未结束、未终止,则返回0
      已经子进程已结束, 则返回子进程的PID
      如果失败, 返回-1

      1. 僵尸进程

        1) 什么是僵尸进程
        僵死进程(死进程):是指该进程已经结束运行,但在进程表中还没有删除它的相关信息。

        2)僵死进程产生的原因
        子进程比父进程先结束,(儿子比父亲先“死”)
        但是又不能在进程表中删除子进程的表项,因为父进程调用wait时还需要这些信息。

        3)僵尸进程的“归宿”
        子进程比父进程先结束后,成为僵尸进程。
        直到父进程也结束,该僵尸进程才真正消亡(从进程表中删除其表项)

        如果父进程被异常终止,则该僵尸进程认init进程为“父进程”
        init进程发现该僵尸子进程后,再把它清除。

        应该尽量避免产生僵尸进程。
        僵尸进程虽不再运行,但仍占用系统的资源!

        main11.c
        测试:gcc main11.c
        ./a.out &
        ps /* 子进程结束后 */

    你知道:

     for (i=0; i<2; i++) {
                fork();
           }
       一共创建了多少个进程?
    
  • 相关阅读:
    POJ 1953 World Cup Noise
    POJ 1995 Raising Modulo Numbers (快速幂取余)
    poj 1256 Anagram
    POJ 1218 THE DRUNK JAILER
    POJ 1316 Self Numbers
    POJ 1663 Number Steps
    POJ 1664 放苹果
    如何查看DIV被设置什么CSS样式
    独行DIV自适应宽度布局CSS实例与扩大应用范围
    python 从入门到精通教程一:[1]Hello,world!
  • 原文地址:https://www.cnblogs.com/Sico2Sico/p/5384223.html
Copyright © 2011-2022 走看看