Linux进程基础知识

327 阅读6分钟

一、 程序、进程和线程的基本概念


  1. 程序

    • 程序就是一个文件,只占用磁盘的空间,是静态概念。
  2. 进程

    • 进程不会占用磁盘空间,系统会给进程分配cpu和内存
    • 每个进程对应一个虚拟地址空间
    • 进程是并发执行的程序在执行过程中分配和管理资源的基本单位,是动态概念。
  3. 线程

    • 线程是轻量级的进程,在Linux环境下线程的本质仍是进程
    • 线程是操作系统调度执行的最小单位。
    • 多个子线程和主线程共用同一个虚拟地址空间
    • 线程和进程一样都会争抢cpu资源
  4. 并行和并发

    • 并行:多个人在同一个时间点干同一件事。
    • 并发:同一个时间段处理若干个工作。
    • 通俗点讲:并行是,我和你在同一个时间点都在跑步。并发是我在游泳的时候你可以看比赛。
      


二、 CPU时间片和进程控制块(PCB)


  1. cpu时间片
  2.        时间片即cpu分配给各个进程运行的时间,每个进程被分配一个时间段,称作时间片,使各个进程从表面上看是同时进行的。
           每个时间片都是有限的,如果时间片结束时进程还在运行,进程将会被中断挂起等待下一个时间片,cpu则会被分配给另一个进程,如果在时间片结束前阻塞或结束,则cpu立即分配给另一个进程,这个行为称作时间片轮转。

  3. 进程控制块(PCB)
  4. Linux内核的进程控制块是task_struct结构体。结构体中包含如下信息:

    • 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,即非负整数。
    • 进程的状态。有就绪、运行、挂起、停止等状态。
    • 进程切换时需要保存和恢复的一些CPU寄存器。
    • 描述虚拟地址空间的信息。
    • 描述控制终端的信息。
    • 当前工作目录。
    • umask掩码。
    • 文件描述符表,包含很多指向filed结构体的指针。
    • 和信号相关的信息。
    • 用户id和组id。
    • 会话和进程组
    • 进程可以使用的资源上限。


三、 进程的创建


  1. 创建进程
  2. 1   //函数及头文件
    2    #include <sys/types.h>
    3    #include <unistd.h>
    4    pid_t fork(void);
    5
    6   返回值类型是pid_t
    7       成功则返回两个值
    8           >0:父进程ID
    9           ==0:子进程ID
    
  3. 结束进程
  4. 1   // exit -> c库函数
    2   #include <stdlib.h>
    3   void exit(int status);
    4
    5   // _exit() -> linux系统函数
    6   #include <unistd.h>
    7  void _exit(int status);
    8
    9  state是返回值,返回给父进程
    
  5. 命令
    • 查看进程
    • 1   ps aux/ajx
      2       a: 显示当前终端下的所有的程序, 包括所有的用户
      3       u: 显示用户信息
      4       x: 打印和tty终端先关的信息
      5       j: 显示更多的用户信息
      
      
    • 杀死进程
    • //查看信号(前面是数值,后面是宏值)
      1   kill -l(注意是字母,不是数字)
      2       1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL  
      3       5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
      4       9) SIGKILL      10) SIGUSR1     11) SIGSEGV     12) SIGUSR2 
      5       13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
      6       17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
      7       21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU 
      8       25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    
      9       29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
      10      35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
      11      39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8 
      12      43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
      13      47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
      14      51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
      15      55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
      16      59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
      17      63) SIGRTMAX-1  64) SIGRTMAX
      
      //杀死进程
      (1)kill -SIGKILL 进程ID(PID)
      (2)kill -9       进程ID(PID)
      
  6. 父子进程的异同点
    • 相同点
      • 子进程刚被创建出来,未进行任何操作时,父子进程之间共享文件描述符表。
      • 子进程刚被创建出来,未进行任何操作时,父子进程之间共享用户区数据。
    • 不同点
      • fork()函数的返回值不同。
      • 进程ID不同。
      • 信号集不同。


四、 进程的回收

  1. 僵尸进程
  2.        子进程结束,但父进程还在运行,并且没有回收子进程的PCB(进程控制块)。这时子进程不占用内存,只有一个PCB,没有用户区数据,不会被系统调度,因此不能称作一个存活的进程。

  3. 孤儿进程
  4.        父进程结束,但子进程还在运行。此时子进程会被初始进程领养并释放。

  5. 进程回收函数
  6. 1   #include <sys/types.h>
    2   #include <sys/wait.h>
    3   pid_t wait(int *wstatus);
    5       返回值:
    6            >0:     则是被回收进程的ID
    7            ==-1:   函数调用失败
            参数:
                是传入参数,记录进程退出状态
    8   pid_t waitpid(pid_t pid, int *wstatus, int options);
    5       返回值:
    6            >0:     则是被回收进程的ID
    7            ==-1:   函数调用失败
            参数:
                pid:      要回收的进程的进程ID
                        <-1:    回收进程组ID为pid绝对值的进程组。 
                        =-1:    回收所有子进程。
                        ==0:     回收当前进程的所有子进程,包括在别的进程组内的
                        >0:      则是被回收进程的ID
                *wstatus:是传入参数,记录进程退出状态
                options:
                        WNOHANG:       设置为非阻塞
                        WUNTRACED:
                        WCONTINUED:
    


五、 exec函数族

  1. 介绍
  2.        exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。
           函数族的函数执行成功后不会返回,只有调用失败了,它们会返回-1,从原程序的调用点接着往下执行。
           如果调用成功调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只有进程ID等一些表面上的信息仍保持原样。

1   #include <unistd.h>
1   extern char **environ;
2   int execl( const char *path, const char *arg, ...);
3       参数:
5           path:  可执行文件的路径
6           arg:   传给可执行文件的参数
7           ...:   代表这个函数是个可变参数,参数数量不定,例如printf
8           
9   int execlp( const char *file, const char *arg, ...);
10     参数:
11          file:  可执行程序的名字,但必须在环境变量path中
12           arg:   传给可执行文件的参数
13           
14  int execle( const char *path, const char *arg , ..., char * const envp[]);
15  int execv( const char *path, char *const argv[]);
16  int execvp( const char *file, char *const argv[]);