#每日Linux小练习#12进程的详细分析
经常被问到进程和线程的区别,今天对进程进行详细的分析讨论。
一、进程的定义
struct task_struct { //这个是进程的运行状态,-1代表不可运行,0代表可运行,>0代表已经停止。 volatile long state;
/* flags是进程当前的状态标志,具体如下: 0x0002表示进程正在被创建 0x0004表示进程正准备退出 0x0040表示此进程被fork出,但是并没有执行exec 0x0400表示此进程由于其他进程发送相关信号而被杀死 */ unsigned int flags; //反应进程状态的信息,但不是运行状态 //表示此进程的运行优先级 unsigned int rt_priority; //该结构体记录了进程内存使用的相关情况 struct mm_struct *mm; //进程号,是进程的唯一标识 pid_t pid; //进程组号 pid_t tgid; //real_parent是该进程的"亲生父亲",不管其是否被"寄养"//该指针指向创建当前进程的的进程,或者是当创建者已经消亡后,该指针指向init进程。 struct task_struct *real_parent; //parent是该进程现在的父进程,有可能是"继父"//一般情况下和real_parent一样,只是当另外一个进程调用了ptrace()系统调用后 struct task_struct *parent; //这里children指的是该进程孩子的链表,可以得到所有孩子的进程描述符 struct list_head children; //同理,sibling该进程兄弟的链表,也就是其父进程的所有孩子的链表 struct list_head sibling; //这个是主线程的进程描述符,也许你会奇怪,为什么线程用进程描叙符表示,因为linux并没有单独实现线程的相关结构体,只用一 个进程来代替线程,然后对其做一些特殊的处理。 struct task_struct *group_leader; //这个是该进程所有线程的链表 struct list_head thread_group; //这个是该进程使用cpu时间的信息,utime是在用户态下执行的时间,stime 是在内核态下执行的时间 cputime_t utime,stime; //comm是保存该进程名字的字符数组,长度最长为15,因为TASK_COMM_LEN为16 char comm[TASK_COMM_LEN]; //打开的文件相关信息结构体 struct files_struct *files; //信号相关信息的句柄 struct signal_struct *signal; struct sigband_struct *sighand; };
./20150814pstree_sleep.sh & pstree -Aup ubuntu| grep -n -A2 -B3 'sh' while [ 0 ] do sleep 2 done
程序./20150814pstree_test.sh
echo "this is $0 ,my PID is $$" while [ 0 ] do # echo "3s has passed" sleep 3 done
Step1:程序运行结果如下:
gonme-terminal(2805)是本图形界面tty7对应的终端程序,tty7下使用bash(2810)运行了20150814pstree.sh(3263)这个进程。
20150814pstree.sh(3263)这个进程又运行了20150814pstree_sleep.sh(3622)这个进程,grep进程,pstree进程
Step2:在原有基础上再开一个窗口(相当于一个bash文件),再次运行20150814pstree.sh程序,
可以看出,多出了bash(3739)这个进程,对应新打开的窗口,之后的20150814pstree.sh(3976)进程,以及其子进程同上面的解释
Step3:此时,将先前的窗口关闭,在新窗口中重新运行20150814pstree.sh程序,
1、bash(3739)的进程号不变
2、20150814pstree.sh的进程号变化了(因为是新的)
3、之前的窗口被关闭了,所以对应的进程消失了,然而它的子进程也消失了
Step4:
此时,键入 ps -l 命令
来分析一下,
bash(3739)->20150814pstree.sh(4533)->sleep(5850)
->20150814pstree_sleep.sh(4534)->sleep(5848)
->ps(5987)
init(1)->20150814pstree_sleep.sh(3918)->sleep(5987)
->20150814pstree_sleep.sh(3977)->sleep(5986)
在前一个窗口中,使用CRTL+C关闭了20150814pstree.sh,而对应的后台运行的子进程20150814pstree_sleep.sh都没有管,成为了“僵尸”进程,就归init管了。
这时候,可以使用kill 指令将其关闭。
本文中代码可以从github上面下载,https://github.com/yifeng152/oneShellPracticePerDay.git
对应文件为20150814pstree.sh