博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux Process Manage
阅读量:7230 次
发布时间:2019-06-29

本文共 2805 字,大约阅读时间需要 9 分钟。

Linux 下的工作都是依靠进程来执行的,控制了进程就相当于控制了 Linux 系统了。这篇博客将通过 Linux 系统的启动登录来探讨进程管理机制,看这种机制如何支撑和左右进程的命运。

什么是进程

先来了解了解什么是进程,程序这个词比较好理解,通常的程序是静态实体,进程是正在运行的程序实体,并且包括这个运行的程序中占据的所有系统资源,比如说CPU(寄存器),IO,内存,网络资源等。进程描述符(PID)是唯一用来标识进程的。

进程的创建

fork 和 exec 分别是进程的分身和变身

在运行级别3下启动 Linux,出现命令行界面需要在“login: ”提示符处输入用户名登录,可以另外找一台机子ssh远程连接,查看一下mingetty进程的执行情况:

# ps -ef|grep mingett[y]root     14450     1  0 14:10 tty1     00:00:00 /sbin/minagetty --noclear tty1 linuxroot     14566     1  0 14:13 tty2     00:00:00 /sbin/minagetty --noclear tty2 linuxroot     14589     1  0 14:16 tty3     00:00:00 /sbin/minagetty --noclear tty3 linuxroot     14591     1  0 14:16 tty4     00:00:00 /sbin/minagetty --noclear tty4 linuxroot     14593     1  0 14:16 tty5     00:00:00 /sbin/minagetty --noclear tty5 linuxroot     14595     1  0 14:16 tty6     00:00:00 /sbin/minagetty --noclear tty6 linux

这里有6个mingetty进程,对应CTRL+ALT+F1~F6六个虚拟控制台。

在tty1输入用户名并按回车,这里先不要输入密码,回到ssh远程登录终端上,再看看mingetty进程,会发现少了PID为14450的mingetty进程,可以利用ps命令检索PID。

# ps -ef|grep 1445[0]root     14450     1  0 15:36 tty1     00:00:00 /bin/login --

PID为14450的进程变成了login进程了。这是因为mingetty进程在exec()系统调用的作用下,转变成了login进程。

exec的作用是舍弃进程原先携带的信息,在进程执行时用新的程序代码替代调用进程的内容。

可以分析一下mingetty进程中运行exec的部分源码:

exec(loginprog, loginprog, autologin? "-f" : "--", logname, NULL);

mingetty进程的工作是接收登录用户名,之后的密码验证处理工作则是 login 进程的工作,当验证结束后,便启动用户的bash进程。

同样的再次检索同一个PID会发现 login 进程保留了原先的相同的进程,而且还多了一个 bash 进程。这是因为 bash 进程的父进程ID是14450,这说明bash进程是作为 login 进程的子进程开始启动的。

exec 和 fork 中进程的变化

┌─────┐│进程  │PID=X  │程序=A  └─────┘   │   ↓┌─────┐│进程     │PID=X    │程序=B   └─────┘
┌─────┐│父进程  │PID=X    ──┓ │程序=A      │└─────┘     │ fork   │        │   ↓         ↓┌─────┐   ┌─────┐│父进程    │子进程  │PID=X    │ PID=Y  │程序=A    │程序=A   └─────┘   └─────┘

通常fork一个进程是指通过父进程创建一个子进程,生成的子进程与父进程只有PID不一样,login 进程通过fork生成一个自身的副本后,还会在子进程通过exec启动 bash 。这样的机制叫做“fork-exec”

childPid = fork();//创建子进程    if (childPid < 0) {        int errsv = errno;        fprintf(stderr, _("login: failure forking: %s"), strerror(errsv));        PAM_END;        exit(0);    }        if (childPid) {//父进程,等待子进程退出    /* parent - wait for child to finish, then cleanup session */        signal(SIGHUP, SIG_IGN);        signal(SIGINT, SIG_IGN);        signal(SIGQUIT, SIG_IGN);        signal(SIGTSTP, SIG_IGN);        signal(SIGTTIN, SIG_IGN);        signal(SIGTTOU, SIG_IGN);//忽略以上信号                wait(NULL);//等待子进程结束        PAM_END;//PAM结束        exit(0);    }    //以下是子进程    /* child */        //(省略部分源码)    childArgv[childArgc++] = NULL;    //登录成功,执行/bin/sh进入shell    execvp(childArgv[0], childArgv + 1);

上面是login.c的源码,可以知道父进程会一直等待子进程结束(wait),父进程才会结束。

进程的结束

在已登录的控制台上输入 exit 进行用户注销,此时exit()系统调用,bash进程会被终止,同时发送CHLD信号给父进程login。接收到CHLD信号的父进程login会退出wait函数,同时结束进程。wait是一个函数,它让父进程在接收子进程CHLD信号之前一直保持休眠状态。

另一方面,子进程在向父进程发送CHLD信号,直到父进程接收为止,子进程一直保持僵尸状态。

博客地址

转载地址:http://uccfm.baihongyu.com/

你可能感兴趣的文章
关于FB4.6插件安装后默认语言环境的更改问题
查看>>
免费分区助手
查看>>
Javascript通过Name调用Function
查看>>
统计当前在线用户数量
查看>>
IntelliJ IDEA 乱码解决方案 (项目代码、控制台等)
查看>>
PHP项目记录
查看>>
.net面试题系列文章七(附答案)
查看>>
FastSocket
查看>>
ionic $ionicSlideBoxDelegate 滑动框事件
查看>>
点击文字,把input type="radio"也选中
查看>>
第一章 Java多线程技能
查看>>
Java 集合系列-第八篇-Map架构
查看>>
springmvc 3.2 @MatrixVariable bug 2
查看>>
React-Native PanResponder手势识别器
查看>>
IOS11 光标错位问题
查看>>
如何设计用户登录
查看>>
linux安装mysql5.7.19
查看>>
Zookeeper+ActiveMQ 集群实现
查看>>
加权有向图问题2----多源最短路径问题(Floyd算法)和关键路径算法
查看>>
logback logback.xml常用配置详解(三) <filter>
查看>>