UNIX/Linux系统命令(4)——进程操作

一.基本概念
1.进程与程序:
程序:存储在磁盘上的文件,包含可执行指令和数据的静态实体
进程:运行中的程序(一个程序可执行多次,加载出多个进程)
进入就是处于活动状态的计算机程序

2.进程的分类:
交互进程:有输入,输出,用户可以根据自己的情况输入数据,得到想要的结果(一般进程)
批处理进程:由脚本加载执行的程序(Linux下的shell,windows下的bat)
守护进程:总是活跃的,后台运行,一般由系统开机是加载执行或root用户手动加载执行

3.查看进程
简单方式:ps,显示当前用户有终端控制权的进程信息
列表形式:ps aux,以列表形式显示详细信息
a 所有用户的终端控制进程
x 所有用户的无终端控制的进程
u 详细信息显示

4.进程的详细信息列表
USER 进程的属主
PID 进程id
%CPU CPU使用率
%MEM 内存使用率
VSZ 占用虚拟内存的大小
RSS 占用物理内存的大小
TTY 有终端控制的显示终端的次设备号,如果五终端控制的显示?
STAT 进程的状态
O 就绪态,等待被调用
R 运行态,Linux系统没有就绪态,就绪态也用R表示
S 休眠态,可以被系统中断(信号)唤醒,转入运行态
T 暂停态,是被SIGSTOP暂停的,当收到SIGCONT信号才能再转入运行态
Z 僵尸态,已经结束停止运行,但父进程还没有回收
< 高优先级进程
N 低优先级进程
l 多线程化的进程
+ 在前台进程组中的进程
s 会话首进程
START TIME 进程的开始时间
COMMAND 进程的可执行文件名

5.父进程与子进程,孤儿进程,与僵尸进程
一个进程A可以创建出另一个进程B,创建者叫父进程,被创建进程叫子进程,父进程启动子进程后,在操作系统的调用下父进程同时执行(同步)
如果子进程先于父进程结束,会向父进程发送SIGCHLD信号,父进程收到信号后,就应该去回收子进程的相关资源,但在默认情况下,父进程忽略该信号也就是说,当子进程结束后,父进程没有回收子进程的资源,那么子进程就变成了僵尸进程
如果父进程先于子进程结束,子进程就变成了孤儿进程,同时被孤儿院(init)收养,然后就变成了init的子进程
二.进程标识符
操作系统会为每个进程分配一个唯一的标识符,采用无符号整数表示,即进程ID
进程ID在任何情况下都是唯一的,但是可以重用,当一进程结束,新创建的进程才可以使用它的进程ID(延时重用)

     pid_t getpid(void)   
     功能:获取进程ID
     pid_t getppid(void);
     功能:获取父进程
     uid_t getuid(void);
     功能:获取当前进程的用户ID
     gid_t getgid(void)
     功能:获取当前进程的组ID

三.fork

 pid_t fork(void);
 功能:创建一个新进程
 返回值:一次调用两次返回,失败返回-1(当进程数超出系统的限制进程创建就会失败)

1.两次返回分别是进程id和0,父进程会拿到子进程的id,子进程返回0,借此可以分别出父子进程,编写不同的处理分支
2.通过fork创建的子进程就是父进程的副本(拷贝)
子进程会获取父进程数据段,bss段,堆,栈,IO流(共享文件指针和标识符),缓冲区的拷贝,与父进程共享代码段
3.子进程会继承父继承的信号处理方式
4.fork函数调用后,父子进程各自执行,谁先返回不一定,但可以使用一些手法来确定谁先执行
5.僵尸进程与孤儿进程的实现

四.进程的正常退出
1.从main函数中return
2.调用标准库中的exit函数
void exit(int status);
功能:调用者立即结束该进程
status:退出状态码,可以在父进程中获取到,子进程给父进程留的遗言
退出前做的事情:
1.先调用事先注册的函数(通过atexit/on_exit)

        int on_exit(void (*function)(int , void *), void *arg);
        功能:注册一个函数,当进程通过exit函数开始结束时调用
        function:函数指针,无返回值,参数1为exit的参数,参数二为on_exit函数的第二个参数
        arg:当function的函数被调用时传递给它的第二个参数
        
        int atexit(void (*function)(void));
        功能:注册一个函数,当进程通过exit函数结束时调用
        function:函数指针,无返回值,无参数
        返回值:成功0,失败-1
        
        2.冲刷(刷新)所有处在未关闭状态的标准的IO流
        3.返回一个整数给操作系统(EXIT_SUCCESS(0)/EXIT_FAILURE(1))
        4.该函数是不会返回的,它的功能实现借助了_exit/_Exit

3.调用_exit/_Exit退出

 注意:这两个函数的功能是一样的
           #include<unistd,h>
           void _exit(int status);
           #include<stdlib.h>
           void _Exit(int status);
           功能:调用的进程会结束,没有返回值
           statu:会被父进程获取到(低八位,一个字节)
           1.进程结束前会关闭所有处于打开状态的文件描述符
           2.把所有的子进程托付给init
           3.向它的父进程发送SIGCHLD信号
           注意:exit函数也会执行以上操作,因此它底层调用了_exit/_Exit
 4.进程的最后一个线程执行了最后一条语句
 5.进程的最后一个线程调用了pthread_exit函数

五.进程的异常退出
1.调用了abort函数,产生SIGABRT信号.
2.进程接收到一些信号(没有捕获处理,或无法捕获处理),
3.进程的最后一线程收到"取消"请求,并做出响应,相当于线程收到了结束"信号"

六.wait/waitpid

 #include <sys/types.h>
    #include <sys/wait.h>
    pid_t wait(int *status);
    功能:等待所有子进程结束,并获取到最终的状态码,只要有一个进程结束就立即返回 
    1.应该是父进程收到子进程发送来的SIGCHLD信号时,调用wait函数回收在进程的资源并获取结束状态  
    2.如果所有子进程都在运行,则wait阻塞
    3.如果已有僵尸进程,wait也会立即返回,回收资源获取结束状态码
    4.如果没有子进程,则返回失败-1
    pid_t waitpid(pid_t pid, int *status, int options);
    功能:等待指定的进程结束,并获取到最终的状态码
    pid:  
           -1 等待任意子进程结束,此时与wait等价
           >0 等待进程号为pid的进程结束,此时只等待一个进程结束
           =0 等在同组的任意子进程结束,此时等待的是整个进程组
          <-1 等待的是进程组id是pid的绝对值的任意子进程结束,此时等待的是整个进程组
    options: 
      WNOHANG       非阻塞模式,如果没有子进程结束就立即退出    
      WUNTRACED     如果子进程处于暂停状态,则返回它的状态
      WCONTINUED    如果子进程从暂停转为继续,则返回它的状态
    1.wait函数只能孤独的等待子进程结束,而waitpid可以有更多的选择
    2.它不光可以等待子进程,也可以等待同组进程,
    3.waitpid可以阻塞也可以不阻塞,
    4.也可以监控子进程的暂停或继续状态

七.vfork

      pid_t vfork(void);
      功能:for的功能基本一致
      区别:通过vfork创建的进程不复制父进程的地址空间(数据段,bss段,,,IO流(共享文件指针和标识符),缓冲区的拷贝),必须通过excl系列函数加载字节的可执行程序
      注意:当执行vfork时,子进程先返回,此时它占用父进程的地址空间,当子进程成功创建后(通过exec加载可执行程序),父进程才返回

八.exec

  功能:加载子进程的执行文件
       int execl(const char *path, const char *arg, ...);
       path:可执行文件的路径
       arg:第一个main函数的参数,最后一个必须由NULL结尾
       int execlp(const char *file, const char *arg, ...);
        file:可执行文件的名字,会从PATH环境变量中查找可执行文件并执行
        arg:第一个main函数的参数,最后一个必须由NULL结尾
       int execle(const char *path, const char *arg,..., char * const envp[]);
       path:可执行文件的路径
       arg:第一个main函数的参数,最后一个必须由NULL结尾
       envp[]:父进程的环境变量表传递给子进程
       int execv(const char *path, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[],char *const envp[]);

九.system

    int system(const char *command);
    功能:执行系统命令的,也可以加载可执行程序
         相当于创建了一个子进程,但子进程不结束,该函数不返回,父子进程不会同时执行.
    该函数的实现应该调用了:vfork,exec,wait等函数

十.进程组
进程组:是由一个或多个进程的集合,每个进程除了有一个进程ID还有一个进程组ID,进程组中的进程归属同一个作业控制(负责完成同一个任务)
同一进程组的进程,会统一接收到终端信号,由fork创建的子进程默认加入了父进程的进程组
每个进程组都有一个组长,进程组的ID就是组长的进程ID

          pid_t getpgrp(pid_t pid);
          功能:获取pid进程的进程组ID 
          int setpgrp(pid_t pid, pid_t pgid);
          功能:设置进程pid的进程组ID,就相当于加入了pgid的进程组
          pgid就是它的组长   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值