linux进程学习笔记

【1】进程的基础
 1)进程与程序
    程序:保存在磁盘上的一组指令的有序集合。静态的,没有任何的执行的概念。
    进程:是程序动态运行的一次执行过程。动态的,具有一定的生命周期,包括创建,调度,消亡。
 2)进程由2部分组成
    用户空间资源:数据段,代码段,堆栈段,BSS段,进程资源,资源自动释放
    内核空间资源:进程标识符,PCB(进程控制块),进程的属性信息,不会主动的释放资源,要需要人为主动回收。
 3)主要的进程标识
  PID 进程PID
  PPID 父进程PID
  注意:PID是一个唯一的,正整数。
 4)进程的执行过程
 创建:每启动(运行)一个进程,内核就会为当前的进程分配内存空间,保存变量,代码等。
 调度:CPU的(优先级)调度,上下文的切换(用户空间和内核空间的切换)。
 消亡:进程结束,需要回收资源,主动回收(调用相关的函数接口)。
 5)Linux中的进程包含三个段
 数据段
 代码段
 堆栈段
 PCB(进程控制块)
 6)进程的种类:
    交互进程:
    该类进程是由shell控制和运行的。交互进程既可以在前台运行,也可以在后台运行,可以与用户直接交互,
    且受终端的控制。
    前台进程-----------受终端的控制
    后台进程------------不受终端控制
    注意:将前台进程变成后台进程 ./a.out &
    批处理进程:
    该是一个进程序列,负责按照顺序启动,该类进程不属于某个终端,不与用户进行交互,在后台运行,称之为进程的集合。
    守护进程:
    长期运行在后台做某些服务,一般在Linux启动时开始运行,系统结束时停止运行。
    本身属于后台进程, 不受终端控制。自己做为会话组组长。

【2】进程的相关命令
  top 动态查看进程的属性信息(PR,NI优先级)
  ps 
  px ajx  查看进程的属性信息
  ps aux  查看进程的属性信息
  特殊:0号进程:内核进程
        1号进程:init进程
        每一个进程都有父进程,除了0号进程(理解用2叉树理解)
  ps  axj 指令:
  ps aux | grep 可执行程序的名称
  ps aux/-aux | grep a.out
        PPID       PID   PGID      SID   TTY      TPGID        STAT (***)    UID     TIME   COMMAND
        0          1      1        1     ?           -1         Ss       0     0:01    /sbin/init
        父亲进程id 进程号 进程组id 会话id 终端     终端进程组id 状态    用户id   时间   进程命程
       
       int getdtablesize(void);   // 得到最大能打开文件描述符个数
       Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will
       display to describe the state of a process:
       D    uninterruptible sleep (usually IO)  // 不可中断睡眠态
       R    running or runnable (on run queue)  // 运行态(正在运行,等待运行)
       S    interruptible sleep (waiting for an event to complete)  // 睡眠态
       T    stopped, either by a job control signal or because it is being traced.  // 停止态
       X    dead (should never be seen)  // 死亡态,瞬间发生,程序员不可见
       Z    defunct ("zombie") process, terminated but not reaped by its parent.  // 僵尸态

       For BSD formats and when the stat keyword is used, additional characters may be displayed:
       <    high-priority (not nice to other users)  // 高优先级进程
       N    low-priority (nice to other users)  // 低优先级进程
       L    has pages locked into memory (for real-time and custom IO) 
       s    is a session leader  // 会话组组长
       注意:进程---》进程组组长---》会话组组长
       l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)  // 进程中包含了线程
       +    is in the foreground process group.  // 前台进程
  kill
  1)kill -l  查看信号
       SIGINT       //默认属性结束进程  ctrl+c
       SIGQUIT      //默认属性结束进程  ctrl+ \
       SIGKILL      // 杀死进程
       SIGUSR1      // 用户自定义的信号,默认结束进程
       SIGUSR2      // 用户自定义的信号,默认结束进程
       SIGCHLD      // 儿子进程死亡,系统会给父亲进程发送 SIGCHLD 信号
       SIGALRM      // 闹钟信号,默认结束进程
       SIGSTOP      // 停止信号, 进程进入暂停态  ctrl + z
       SIGTSTP      // 停止信号
       SIGCONT      // 恢复运行信号
  注意:SIGKILL,SIGSTOP不能被捕捉,忽略,屏蔽。
  2)kill 向指定的进程发送信号
  kill +信号的名称(通过kill -l查看得到的信号)+PID 向执行的进程发送信号。
  注意:只有 kill -9 + pid 是具有杀死进程的功能,其他的数字没有。 
  bg  将挂起的进程放到后台执行(暂停进程)
  ./aout &  将普通执行的程序放到后台执行
  fg  将后台进程放到前台执行
  注意:bg 1
        bg 2
        fg 1
        fg 2
        ...
  nice 在进程启动前改变进程的优先级,并将进程运行起来
  sudo nice -n (优先级)(可正可负)+ ./a.out
  sudo nice -n -10 ./3
  renice 在进程运行过程中改变进程的优先级
  sudo renice -n +(优先级数)+pid
  sudo renice -n -15 pid
  ps -le
 
【3】进程的相关系统调用
    源进程与新创建进程的关系:子进程精确复制父进程的代码,复制了代码段,数据段,堆栈段,BSS段,文件
    描述符,缓冲区空间;空间各自独立,PID,PPID,ino号,进程PCB控制块没有复制。
    1)进程的创建---fork
     #include <unistd.h>
        pid_t fork(void);
    函数的功能:创建新的子进程(在已有的进程的基础上)
    参数:无
    返回值:pid < 0 出错 没有创建子进程
            pid =0 执行子进程
            pid >0 执行父进程
    注意:孩子进程从fork之后执行,因为在fork之后才出现父子进程。
          父子进程的执行顺序不确定,谁先抢占到CPU谁先执行。
          谁先执行并不代表谁先执行完。
          父子进程没有分开执行
          父子进程分开执行
    2)getpid
     #include <sys/types.h>
     #include <unistd.h>
     pid_t getpid(void);
    函数的功能:获取当前进程的PID
    参数:无
    返回值:当前进程的PID
    getppid
     pid_t getppid(void);
    函数的功能:获取当前进程的父进程PID
    参数:无
    返回值:当前进程的父进程PID
    3)子进程对父进程缓冲区的处理
    结论:创建父子进程,子进程精确复制父进程,复制包括数据段,代码段,BSS段,堆空间,栈空间,文件描述符(特例),     用户空间的缓冲区,当子进程复制父进程的缓冲后,随着子进程结束,会刷新缓冲区当中的数据,所以造成在fork之前的打印语句会执行2次。
    注意:子进程是在fork语句之后执行的。
     子进程对父进程打开的文件描述符的处理
     注意:虽然子进程复制用户空间父进程的文件描述符,但是在内核空间对应的文件管理表项中的文件指针是共享的,====》共享偏移量
    4)僵尸进程和孤儿进程
      1>僵尸进程是如何产生?
      父进程活着,儿子进程死了,但是父进程并没有为儿子进程回收尸体,从而产生僵尸进程
      2>如何避免僵尸进程?
       1)形成孤儿进程---解决僵尸进程。
       2)父进程活着,儿子进程死了,让父亲进程主动调用回收函数去回收儿子进程的资源(wait,waitpid)
      3>孤儿进程是如何产生的?
      当父亲进程优先于子进程结束,子进程被init(1号进程)收养,此时将这个进程称之为孤儿进程。
      注意:孤儿进程的产生时一个正常的现象。
    5)进程的退出
    exit----结束一个进程,会刷新缓冲区
    _exit-----结束一个进程,不会刷新缓冲区
    注意:如果程序正常结束也会刷新缓冲区

    exit/_exit与return的区别
    1)return 结束一个函数体,函数体结束,进程不一定结束
    2)exit/_exit结束一个进程,进程结束,函数体一定结束。
    6)wait/waitpid
    wait----回收任意一个子进程的资源


    #include <sys/types.h>
        #include <sys/wait.h>
    pid_t wait(int *status);
    函数的功能:阻塞等待回收子进程的资源
    参数:status 进程结束时的状态信息
    返回值:成功返回回收子进程的pid
            失败-1
    waitpid---自己指定回收某一个子进程的资源。
    pid_t waitpid(pid_t pid, int *status, int options);
    函数的功能:回收特定子进程的资源
    参数:pid 要回收子进的pid
          pid <-1 回收当前调用进程|pid|等于同组pid的任意子进程
          pid =-1 回收任意一个子进程的资源 ==wait
          pid =0 回收同组进程下的任意一个子进程
          pid >0 回收指定子进程的pid
          status 子进程结束时的状态
          options   0   阻塞
                   WNOHANG 非阻塞       
    返回值:成功返回子进程pid 
            WNOHNAG 没有子进程结束 0
            失败-1;
    7)阻塞与非阻塞(银行办业务)
    阻塞:一直等待条件的发生,直到得到结果,保证了结果。
    非阻塞:等待条件的发生,但是不一定等待到结果,保证了时间。
    8)exec族函数---在子进程当中启动新的程序
     execl
       #include <unistd.h>
       int execl(const char *path, const char *arg, ...);
       函数的功能:在子进程中运行新的程序代码
       参数:path 要执行程序的路径+名称 
       注意:path必须是一个绝对路径
     execlp
     int execlp(const char *file, const char *arg, ...);
       函数的功能:在子进程中运行新的程序代码
       参数:path 要执行程序的路径+名称
       注意:文件的名称可以不用写绝对路径,可以在当前的环境变量下去寻找。
     execle
     int execle(const char *path, const char *arg,
                  ..., char * const envp[]);
     函数的功能:在子进程中运行新的程序代码
     注意:path必须是绝对路径,最后要以一个新的指针数组结束。
     execv
     int execv(const char *path, char *const argv[]);
       函数的功能:在子进程中运行新的程序代码
       注意:path是一个绝对路径
             只有2个参数,没有可变参数
             结尾以指针数组结束
       先定义一个指针数据,将要运行的命令写入指针数组,然后将指针数组的名称传入
     system
     #include <stdlib.h>
     int system(const char *command);
    函数的功能:在当前运行的进程当中启动新的程序
    参数:command 命令
    返回值:成功返回非负数
            失败-1
    9)守护进程
        守护进程的定义:守护进程,也就是通常所说的Daemon进程,是Linux中的后台服务进程。它是一个生存期较长的进程,
       通常独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件
       守护进程常常在系统启动时开始运行,在系统关闭时终止
       Linux系统有很多守护进程,大多数服务都是用守护进程实现的
        守护进程创建的步骤:
        1,创建子进程,父进程退出
           fork
        2,在子进程中创建新会话 ,并且成为会话组组长
          setsid
        3,改变当前目录为根目录
          chdir
        4,重设文件权限掩码 
           umask---放开权限
        5,关闭文件描述符 
            getdtablesize
        6,做服务
            write
            read
        
          

猜你喜欢

转载自blog.csdn.net/xiaohu1996/article/details/81252152
今日推荐