Linux2--进程

Linux 进程 ---- 看的视频是华清远见的曾老师的视频。看的书籍是Linux 编程技术详解。

多进程 多线程,是多任务程序的一种机制。
多任务:比如QQ可以同时和多人聊天,下载和上传。

第一讲:

进程的概念

程序: 可执行程序,存放在磁盘上的指令和数据的有效的集合(文件)
静态的
进程:执行一个程序所分配的资源的总称。
进程是程序的一次执行过程
动态的,包括创建,调度,执行和消亡。

进程包含的内容

进程–>正文段–用户数据段–系统数据段—》程序

系统数据段—>进程控制块–>cpu寄存器的值–>堆栈。

进程控制块:(pcb: Process control block)
进程表示 PID: (一个正整数)
进程用户:
进程状态,优先级
文件描述符表:存档进程打开的所有文件的信息,

寄存器的作用:
pc: program counter(程序计数器)(下一条指令的地址)
进程:在宏观上是并发的。在微观上是顺序执行的。
堆栈:
栈(所有的局部变量都在栈上被创建,(函数的参数,返回值)也都在栈上被自动释放)

进程的类型:
交互进程:在shell下启动,在前台运行,也可以在后台运行。(默认在前台运行)

(前台进程可以往终端输入也可以往终端输出)
(后台进程无法从终端读取输入,但是可以往终端输出)

批处理进程:和在终端无关,被提交到一个作业队列中,以便顺序执行。
(一般是和终端无关,由系统管理员用到,开发很少用到)

守护进程:和终端无关,一直在后台运行
(服务器大都以守护进程的形式存在。)

进程的状态

运行态:(正在运行,可运行(准备运行))

等待态:(进程在等待一件事情的发生或者某种系统资源)
可中断:
不可中断:

停止态:
进程被终中止,收到信号后可以继续运行
死亡态:已经终止进程,但是pcb没有被释放。
在这里插入图片描述

第二讲

查看进程信息(熟练)

ps

查看系统进程快照 ( Process Status)
ps -ef:显示所有的进程信息:

在这里插入图片描述
这个是我在我的电脑上截取的:
UID:进程所有者,创建进程用户的id
pid: 每个进程的进程号 ppid:每个进程的副进程号
stime:进程的开始时间 TTY:进程所关联的终端
TIME:进程执行时占用的时间
CMD:进程所对应的程序的名称

ps-ef|more

ps-ef|grep test在这里插入图片描述
在Linux 虚拟机中创建一个简单的程序,让他空跑。在另一侧我们采用 ps -ef |grep test 直接打印出我们需要的信息。(我们可以看到他的资源占用率时99% ,整个资源基本都被占用了)

ps aux

可以显示进程当前的状态。
在这里插入图片描述
在原来的函数上,新加入 getchar();这个函数会一直等待输入,直到有信息输入回车时,才会进入运行状态,具体的状态的描述:如下 man ps
在这里插入图片描述

top 查看进程动态信息(每隔0.3s就会重新刷新一次信息)

在这里插入图片描述

/proc 查看进程详细信息

在这里插入图片描述

在这里插入图片描述

改变进程优先级(熟练)

nice

按用户指定的优先级进行运行
nice值是: -20 ---- 19 (-20 优先级最高!!默认值是0)
通过TOP命令查看:在这里插入图片描述

通过nice来更改优先级的值。
在这里插入图片描述

renice

renice 改变正在运行进程的优先级(改变已经有的优先级)
在这里插入图片描述
强调一点:普通的用户只能降低优先级。(管理员可以提高和降低优先级)

前后台进程切换(熟练)

jobs 查看后台进程

(后台进程,也称为后台作业)
新建两个后台任务:
通过jobs来查看后台的进程
在这里插入图片描述

fg 把后台运行的进程放到前台运行

用于将后台作业(在后台运行的或者在后台挂起的作业)放到前台终端运行
Foreground
在这里插入图片描述
通过fg命令:把后台的任务,变成前台的任务。

bg 将挂起的进程在后台运行

第三讲:

创建子进程

创建进程  --fork
#include <unsigned.h>
pid_t  fork(void)

创建新的进程,失败时返回-1;
成功时: 父进程 返回 子进程的进程号,  子进程返回0 ( 为了区分父子进程,通过fork返回值进行区分 )

父子进程

子进程继承了父进程的内容,(子进程几乎继承了父进程所有的东西)(但是他们的pid ppid 不同)

父子进程有独立的地址空间,互不影响。(他们对应的物理内存时不一样的,有自己独立的代码和数据)【Linux 用来提高效率也采用了一些其他的技术】

若父进程先结束

子进程成为孤儿进程,被init进程来收养。
一个进程在他的生命周期内,进程号不会变化,但是父进程号会发生变化

若子进程先结束:
父进程没有及时的回收,子进程就会变成僵尸进程。
当进程结束的时候,进程的相关资源都已经被释放了。但是进程的PCB 没有被回收,(pcb存放的进程的返回值,以及结束方式)系统规定 必须由父进程来进行回收。

父进程一定是从main()函数开始执行,
那么子进程是从什么地方开始执行?
子进程从 fork ()的下一条指令开始执行。

父子进程谁先执行?
通常是父进程先执行,但是不确定,要看系统先调度谁!

父进程能够多次调用fork?子进程呢?
父进程可以多次调用fork,创建子进程,需要去回收
子进程也可以创建新的子进程,叫做孙子进程。

结束进程

exit

_exit

他们的参数一样,
void exit (int status);
void _exit (int status);

结束当前的进程并将status返回,
exit结束进程时会刷新(流),缓冲区

第四讲:

如何在进程中去执行另外一个函数。

进程-- exec函数族

进程调用exec函数族执行某个程序,
进程当前的内容被指定的程序替换

实现父子进程执行不同的程序
父进程创建子进程
子进程调用exec函数族
父进程不受影响

shell基本的工作原理相当于父进程,shell创建的子进程里面调用exec进行运行指定的程序。

execl

execlp

execl
execlp

#include <unistd.h>
int execl (const char *path ,const char *arg,......)
//执行指定的Path所对应的内容
//成功没有返回值,执行指定的程序
//失败返回-1(如没有创建,没有权限)
// path 执行的程序的名称,包含路径
//arg ...传递给执行的程序的参数列表


int execlp(const char *file ,const char *arg,......)
file 执行的程序的名称,在path中查找 。


在程序中执行ls命令,显示/etc目录下所有的文件的详细信息

if(execl("/bin/ls","ls","-a","-l","/etc",NULL)<0){
perror("execl");
}

if(execlp("ls","ls","-a","-l","/etc",NULL)<0){
perror("execl");
}

//只有第一个参数不同,execl 需要进行路径的指定,execlp在path中寻找,因此不用指定路径,只需要指明函数名称。

execv

execvp

#include <unistd.h>
int execv (const char *path ,const char *argv[],......)
//V 代表是一个数组。
//把要传的参数都放在数组里,
//成功时,运行指定的程序;失败时返回EOF
argv[] 封装成指针数组的形式

执行ls命令,显示etc目录下的所有的文件的详细信息
char *arg[]={"ls","-a","-l","/etc",NULL};
if(execv("/bin/ls",arg)<0)
{
	perror("execv");
}

//第二种形式时:不需要路径。
if(execvp("ls",arg)<0)
{
	perror("execv");
}




进程–system

#include <unistd.h>
int system (const char *command )

最简单的时使用system进行执行一个新的程序。

第五讲

wait



//进程回收
//子进程结束时由父进程进行回收
//孤儿进程由init 进程回收

//若没有及时回收会出现僵尸进程。

#include <unistd.h>
pid_t wait(int *status)

//整形的指针参数
//返回值是  pid_t的类型,相当于一个整形

成功回收一个子进程时,回收子进程的进程号:失败时返回EOF
若子进程没有结束,父进程会一直阻塞
若有多个子进程,哪个先结束就先回收哪一个子进程。返回结束的子进程的进程号。
status 指定保存子进程返回值和结束方式的地址。
(定义一个整形变量,把整形变量的地址传进去。而不是直接定义一个整形的指针,因为定义好之后,是一个随机数
相当于一个野指针)
status 为NULL表示直接释放子进程PCB ,不接收返回值。


int status;
pid_t pid;

if((pid=fork())<0){
	perror("fork");
	exit(-1);
}
else if(pid==0){
	sleep(1);exit(2);
}
else {
	wait(&status);
	printf("%x\n",status);
	}

返回值和结束方式

子进程exit /_exit /return 返回某个值(0-255)

父进程调用wait(&status)回收

WIFEXITED(status) //判断子进程是不时正常的结束。
WEXITSTATUS (status) //获取子进程的返回值
WIFSIGNENALED(status) //判断子进程是否被信号结束
WTERMSIG(status) //获取结束子进程的信号类型

waitpid

#include <unistd.h>
pid_t  waitpid (pid_t pid ,int *status,int option);

成功时返回回收子进程的pid或者0;失败时返回 EOF
pid可用于指定回收哪个子进程或者任意子进程。
status 指定用于保存子进程返回值和结束方式的地址
option 指定回收方式,0或者WNOHANG  //非阻塞

waitpid(pid,&status,0)//指定回收某一个子进程,pid进程号  阻塞的方式,子进程没有结束,
//父进程就一直阻塞


waitpid(pid,&status,WNOHANG  )//非阻塞的方式。如果子进程结束了返回子进程的进程号
//如果子进程没有结束,父进程也会立刻返回,但是返回值时0.


waitpid(-1,&status,0)//回收当前进程的任意一个子进程。相当于wait

waitpid(pid,&status,WNOHANG  )//非阻塞 回收当前进程的任意一个子进程。

第六讲

守护进程特点

会话、控制终端

创建守护进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值