Linux进程管理

*1、进程与程序
程序就是存储在磁盘上的可执行文件,程序被加载到内存中开始运行进程。
一个程序被多次加载时生成多个进程
进程就是处于活动状态的计算机程序

****2、进程的分类****

    进程一般分为三种类型:交互进程、批处理进程、守护进程
    守护进程一般处于活跃状态,运行在后台,由系统在开机时通过启动脚本来自动创建


**4、父进程、子进程、孤儿进程与僵尸进程**
    一个进程可以被另一个进程创建,创建者叫父进程,被创建者叫做子进程,子进程被父进程启动后会在操作系统的调用下同时运行
    
    当子进程先于父进程结束时,子进程会向父进程发送SIGCHLD信号,此时父进程应该去回收子进程的相关资源,如果没有回收,子进程就会变成僵尸进程
    僵尸进程:该进程已经死亡,但是它的父进程没有立即回收它的相关资源,该进程就进入了僵尸状态
    孤儿进程:父进程先于子进程结束,子进程就变成了孤儿进程,此时孤儿进程会被孤儿院(init守护进程)领养,init就是该孤儿进程的父进程

**5、进程标识符**
    每个进程都有一个非负整数表示的唯一表示,即是它的进程ID/PID
    进程ID在任何时候都是唯一的,但可以重用,进程一旦结束后它的PID会被系统回收,过一段时间才可以重新分配给其他新创建的进程使用(延时重用)

    pid_t getpid(void);
    功能: 获取当前进程的进程ID

    pid_t getppid(void);
    功能: 获取当前进程的父进程的ID
    
    init的进程ID永远是1

创建进程:
int system(const char *command);
功能:执行一个可执行文件,这样就创建了一个子进程
command:可执行文件的名字,根据环境变量PATH去找
返回值:子进程结束后才返回
该函数的实现调用了fork和waitpid函数,其实相当于创建了一个子进程,子进程加载了可执行文件【调用者和commade之间,类似爷爷与孙子的关系】

pid_t fork(void);
功能:创建子进程
返回值:一次调用两次返回,子进程返回0,父进程返回子进程的ID,当进程的数量超过系统的限制会创建进程失败,返回-1
通过fork创建的子进程会拷贝父进程(数据段、bss段、堆、栈、IO缓冲区)等数据区,与父进程共享代码段,子进程会继承父进程的信号处理方式
该函数调用后父子进程各自独立运行,谁先返回并不确定,但是可以通过睡眠确定让哪个进程先执行
可以根据返回值的不同来让父子进程进入不同的分支,执行不同的代码
通过fork创建的子进程可以共享父进程的文件描述符

pid_t vfork(void);
功能:以加载可执行文件方式来创建子进程
返回值:子进程返回0,父进程返回子进程PID

子进程先返回,此时子进程并没有创建成功,需要加载一个可执行文件来替换当前子进程的所有资源,完成替换的子进程才算创成功,此时父进程才能返回
使用exec系统函数加载可执行文件:
int execl(const char *path, const char *arg, ...);
path:可执行文件的路径
arg:命令行参数,一般第一个就是可执行文件的名字,至少有一个,以NULL结尾

int execlp(const char *file, const char *arg, ...);
file:可执行文件名字,会根据环境变量PATH的路径来查找可执行文件
arg:命令行参数

int execle(const char *path, const char *arg,..., char * const envp[]);
path:可执行文件的路径
arg:命令行参数
envp:环境变量表,父进程可以在加载子进程时把环境变量表传递给子进程,这样父子进程就共用一个环境变量表

int execv(const char *path, char *const argv[]);
path:可执行文件的路径
argv:指针数组,由传递给子进程的字符串组成,以NULL结尾

int execvp(const char *file, char *const argv[]);
file:可执行文件的名字
argv:指针数组,由传递给子进程的字符串组成,以NULL结尾

int execvpe(const char *file, char *const argv[],char *const envp[]);
file:可执行文件的名字
argv:指针数组,由传递给子进程的字符串组成,以NULL结尾
envp:环境变量表,

注意:exec系列函数正常是不会返回,当加载子进程可执行文件失败时会返回-1。
以exec系列函数创建的子进程不会继承父进程的信号处理函数,但是能继承父进程的信号屏蔽

练习2:实现出孤儿进程、僵尸进程,并通过ps命令查看确认。

进程的正常退出:
1、在main函数中执行return n,该返回值可以被其父进程接收
2、调用了exit函数,该函数是标准库函数
void exit(int status);
功能:在任意时候调用了此函数都可以结束进程
status:结束状态码,与return函数中的返回值效果一样
注意:该函数不会返回

    进程退出前完成
    int atexit(void (*function)(void));
    功能:注册一个进程结束前要执行的函数
    
    int on_exit(void (*function)(int , void *), void *arg);
    功能:注册一个进程结束前要执行的函数
        int:return的值或者exit函数的参数
        arg:会在进程结束时自动传给function函数的第二个参数
        
        调用exit会进行的事情:
        1、先调用事先通过atexit/on_exit注册过的函数,如果都注册了执行顺序与注册顺序相反
        2、冲刷并关闭所有打开状态下的标准IO流(fopen)
        3、该函数的实现了调用了_exit/_Exit

3、调用 _exit/_Exit 函数    
    void _exit(int status);
    功能:结束进程,由系统提供

    void _Exit(int status);
    功能:结束进程,由标准库提供
       1、它们的参数会被父进程获取到
       2、进程结束前会关闭所有打开状态下的文件描述符(open)
       3、给父进程发送SIGCHLD信号
       4、该函数也不会返回

4、进程的最后一个线程执行返回语句
5、进程的最后一个线程执行pthread_exit函数

进程的异常终止:
1、进程调用了abort函数,产生了SIGABRT信号
2、进程接收某些信号,可以是其它进程发送,也可以是自己发送的,还可能是自己的错误导致的
3、进程的最后一个线程接收到了"取消"操作,并对此作出响应

这三种结束方式导致父进程无法获取结束状态码,所以叫做异常终止

注意:
    不管进程是如何结束都会执行同一段代码,关闭所有打开状态下的文件描述符,释放所有的内存
    无论子进程是正常结束或是异常终止,都会向父进程发送SIGCHLD信号

子进程的回收:
对于任何结束方式,都希望父进程能够知道,通过wait、waitpid函数可以知道子进程是如何结束的以及结束状态码

pid_t wait(int *status);
功能:等待子进程结束,并获取结束状态码
返回值:子进程PID
    1、如果所有的子进程都在运行,则阻塞
    2、如果有任意一个子进程结束,立即返回该子进程结束状态码和PID
    3、如果没有子进程则立即返回-1

    WIFEXITED(status)   判断子进程是否是正常结束,如果是则返回真
    WEXITSTATUS(status) 如果子进程是正常结束的,可以获取正确的结束状态码,只获取低8位
    WIFSIGNALED(status) 判断子进程是否是异常终止,如果是
    WTERMSIG(status)    如果子进程是异常终止的,可以获取导致异常终止的信号编号

注意:
    由于wait函数可能会阻塞,因此不适合放在父进程业务逻辑中间来调用,因此,可以利用SIGCHLD信号来注册一个信号处理函数,在处理函数中来调用wait函数,这样既可以获取结束子进程的信息,也会不影响父进程的正常业务逻辑。

pid_t waitpid(pid_t pid, int *status, int options);
功能:指定回收某个或某些进程
pid:
    < -1    等待属于abs(pid)的编号的进程组中的进程结束
    -1      等待任意子进程结束,功能等同于wait
    0       等待同组的任意进程结束
    >0      只等待pid该进程结束  
status:进程结束状态码,与wait的等价
options:
    0         阻塞模式,相当于wait
    WNOHANG 非阻塞模式,如果没有子进程结束,立即返回 
    WUNTRACED   如果有进程处于暂停状态时,返回该进程的状态码
    WCONTINUED  如果有进程从暂停状态转为继续运行,返回该进程的状态码

    WIFSTOPPED(status)  判断进程是否处于暂停状态,是则返回真
    WSTOPSIG(status)    获取导致进程暂停的信号
    WIFCONTINUED(status) 判断进程是否由暂停态转为运行态,是则返回真
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值