进程使用的总结

当一个知识点,长时间不用的话,那么就会很容易的遗忘,这是一个很正常的规律。所以学而时习之,对我们非常有必要。

那么,这边文章就是对以前学习的进程进行复习和回顾的作用。

我们很容易的知道进程就是程序的一次执行过程,每个进程创建的时候有独立的4GB的空间,有自己的代码段,数据段,堆栈等资源。

linux系统下主要包括下面几种进程: 交互式进程,批处理进程,守护进程

一 、运行进程需要那些资源 ?
 
CPU资源 ,内存资源,时间片资源 

二 、进程与程序 

程序:一个存放在磁盘上的可执行文件 

进程:是程序的一次执行过程,伴随着资源的分配和释放。相对于OS而言。

三 、进程的组成

栈 ,堆,ro data,data段,bss段,代码段,一组寄存器值[pc]

四 、Linux 对进程描述 

PID   :标识一个进程
PPID :标识父进程 

进程内存空间 

进程状态 : 
(1)运行状态:(TASK_RUNNING)进程正在运行,或者正在运行队列中等待调度。
(2)可中断的阻塞状态(TASK_INTERRUPTIBLE):可以被信号中断,接收到信号则被唤醒变为运行的状态,
(3)不可中断的阻塞状态(TASK_UNINTERRUPTIBLE):不会处理信号,所以信号不能改变它的运行状态,只有在它所等待的事件发生的时候,进程才被显示的唤醒。
(4)暂停状态(TASK_STOPPEND):进程的执行被暂停,当进程收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOUT等信号,就进入暂停状态。
(5)僵死状态(EXIT_ZOMBIE):子进程结束而没有被父进程回收的状态 。
    linux首先把终止的进程设置为僵死状态,这个时候进程已经无法运行,它的存在只为父进程提供信息,父进程在某个时间调用wait函数族,回收子进程的退出状态,随后子进程占用的所有资源被释放。
(6)消亡状态(EXIT_DEAD):这是最终状态,当父进程调用wait函数族后,子进程彻底的由系统删除。


Linux 用task_struct 结构体描述一个进程 

五、 进程相关命令

Linux内核通过唯一的进程标示符PID来标示每一个进程。
(1)查看PID和PPID 
Linux系统中获得当前进程的进程号(PID)
父进程号(PPID)的系统调用函数非别为getpid(),和getppid()

ps -ef | grep 进程名或进程号 

(2)查看进程的状态 

ps aux  | grep 进程名或进程号 

D : 不可中断等待态 
S : 可中断的等待态 
T : 停止态 
Z : 僵尸态 
R : 运行态 

(3)给进程发信号 

kill -信号的序号  PID 

查看信号的序号:
kill -l

或 
killall -信号的序号  进程名  

(4)运行程序的时候,指定进程的优先级 

nice  -值  可执行文件 

nice值 [-20-19]

例如:
nice  -10   ./while 
nice --10   ./while 

(5)更改已经运的进程nice值 

renice  nice值  PID 

例如:
renice   10  1235 
renice  -10  1235 

六 、创建子进程 

pid_t fork(void);
功能:
创建一个子进程 ,fork(0函数通过复制当前的进程创建一个子进程,子进程和父进程的区别仅仅在于不同的PID,PPID,和某些资源以及统计量。
返回值:
成功给父进程返回子进程的PID,给子进程返回0,失败返回-1 

创建子进程过程:复制父进程来创建子进程 [复制内容:代码段共享,其他都复制] 

思考: 创建完子进程后,父进程从fork的下一条语句执行,子进程为什么也是从fork的下一条语句执行?
    创建子进程的时候拷贝父进程的PC寄存器值 ,而PC寄存器的作用就是确定程序的下一条执行语句。


pid_t vfork(void);
功能:
创建一个子进程 
返回值:
成功给父进程返回子进程的PID,给子进程返回0,失败返回-1 


vfork 与 fork区别:
(1)fork创建的子进程后,父子进程执行的顺序不确定并且父子进程的地址空间是独立的
(2)vfork创建完子进程后,保证子进程先执行,父进程在子进程结束或子进程调用了exec函数族后,才开始运行。
   并且父子进程共享同一个地址空间[如果子进程调用了exec函数族,则子进程会独立出来]

七 、exec函数族

功能 : 在一个进程中执行另外一个程序

Linux下使用exec函数族主要有两种情况:
(1)当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用exec函数族中的任意一个函数让自己重生。
(2)如果一个进程想执行另外一个程序,那么它就可以调用fork()函数新建一个进程,然后调用exec函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新的进程(这种情况非常普遍

思考 : exec函数族如何执行另外一个程序 ?
用新程序的代码段,数据段,堆栈替换原程序,只保留原进程的PID,其他全部替换

实际上, 在Linux中并没有exec()函数,而是有6个以exec开头的函数:下面将慢慢的解释常用的几种

l  :参数以列表的形式传递
int execl(const char *path, const char *arg, ...);

参数:
@path 可执行程序的路径 
@arg  可执行程序的名字
@arg1 给可执行程序传递的第一个参数 
@arg2 给可执行程序传递的第二个参数 
...
@最后一个参数写成NULL 

返回值:
成功返回0,失败返回-1 

例如:执行/bin/ls ,传递的参数-l 

execl("/bin/ls","ls","-l",NULL);

v:参数以指针数组的形式传递 

int execv(const char *path, char *const argv[]);

char *p_arry[] = {"ls","-l",NULL};

execv("/bin/ls",p_arry);

p:执行的可执行程序从PATH环境变量中搜索

int execlp(const char *file, const char *arg, ...);

execlp("ls","ls","-l",NULL);
------------------------------------------------------------

int execvp(const char *file, char *const argv[]);

char *p_arry[] = {"ls","-l",NULL};
execvp("ls",p_arry);

 exec函数族 

e:执行程序的时候,可以给程序传递环境变量 

int execle(const char *path, const char *arg,..., char * const envp[]);

char *envp[] = {"PATH=/home/linux","TEST=HELLO WORD",NULL} ;

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。