概述
Linux 基础
- 进程
- 1 进程查看命令 ps、pstree、job
- 2 进程的状态
- 3 进程间的关系
- 3.1 父进程与子进程,frok()、vfrok()
- 3.2 进程组
- 3.3 会话
- 4 进程间通信 IPC
- 4.1 管道 pipe
- 4.2 信号
进程
进程,表示程序的运行过程,表示动态的运行。
进程的生命周期。程序运行结束后也就意味着进程终止
- 进程终止(程序结束)的方式
正常终止:
1、main()函数中通过 return 语句返回来终止进程;
2、应用程序中调用库函数 exit()终止进程
3、应用程序中系统调用_exit()或_Exit()终止进程
异常终止:
1、应用程序中调用 abort()函数终止进程;
2、进程接收到一个信号,譬如 SIGKILL 信号。
1 进程查看命令 ps、pstree、job
ps
ps -aux:列出所有进程和状态
ps -ajx:列出所有进程和状态
ps -ef:列出所有进程
ps -l:列出和当前用户有关的进程和状态
ps -u:用户名:查看某一用户的进程状态
ps -j:列出PID SPID
jobs 查看当前后台的进程状态
jobs -l:除了列出进程号外,同时列出PID
jobs -r:列出仅仅在后台运行的进程
jobs -S:列出仅仅在后台暂停的进程
pstree 进程树
2 进程的状态
Linux 系统下进程通常存在 6 种不同的状态(ps -aux命令可查)
1、R 运行态 和 就绪态
运行态 该进程当前正在被 CPU 调度运行
就绪态 该进程得到 CPU 调度就会变成 运行态
2、S 可中断睡眠状态(浅度睡眠)
进程在等待某个事件、资源有效(IO事件、信号唤醒、中断唤醒)而被系统挂起
3、D 不可中断睡眠状态(深度睡眠)
进程在等待某个事件、资源有效而被系统挂起,不能被信号、中断唤醒
4、T 停止态。
表示进程暂停运行,一般可通过信号将进程暂停
5、Z 僵尸态
该进程已经结束、但其父进程还未给它“收尸”
6、X 死亡态
首字母跟着的其他字母含义
s 表示当前进程是一个会话首领进程
I 表示当前进程是一个多线程进程
N 表示低优先级
< 表示高优先级
+ 表示当前进程处于前台进程组
3 进程间的关系
进程间存在着多种不同的关系:无关系(相互独立)、父子进程关系、进程组、会话。
3.1 父进程与子进程,frok()、vfrok()
PID:进程的ID (每一个新进程都有一个唯一的PID)
PPID:父进程的ID
所有进程的父进程: init
getpid() 返回其子进程pid
getppid() 返回其父进程pid
- 创建子进程 frok()
子进程会拷贝父进程的数据段、堆、栈,并且拷贝父进程打开的所有文件描述符
子进程和父进程各自在自己的进程空间中运行 ,父进程与子进程并不共享这些存储空间
- 创建子进程 vfrok()
是为了弥补frok() 的缺点,所以引入 vfrok()
fork 创建子进程之后,子进程会拷贝父进程的数据段、代码段、堆栈等
将其拷贝到自己的进程空间中;当子进程调用exec 函数加载一个新的程序时,
新的程序又会替换掉这些拷贝过来的代码段、数据段、堆栈等,
导致之前的拷贝工作白忙活一场,所以也导致在这种情况下,
fork 函数的效率比较低!
- frok()、vfrok()的区别
区别1
fork 会为子进程创建一个新的地址空间 (也就是进程空间),
子进程几乎完全拷贝了父进程,包括数据段、代码段、堆、栈等;
vfork 函数,子进程在终止或者成功调用exec 函数之前
子进程与父进程共享地址空间,共享所有内存,包括数据段堆栈等
区别2:
fork调用之后,父、子进程的执行次序不确定;父进程概率比子进程概率大
vfork函数会保证子进程先运行,父进程此时处于阻塞、挂起状态,
子进程终止或成功调用exec函数之后,父进程才会被调度运行。
3.2 进程组
PGID:进程组的ID
返回进程组ID
getpgrp()
getpgid(pid号)
每个进程必定属于某一个进程组、且只能属于一个进程组,每一个进程组有一个组长进程,组长进程的 ID 就等于进程组 ID; 在组长进程的 ID前面加上一个负号即是操作进程组
进程组的生命周期从被创建开始,到其内所有进程终止或离开该进程组;只要进程组中还存在一个进程,则该进程组就存在
3.3 会话
SID:会话ID
返回会话ID
getpsid(pid号)
会话是一个或多个进程组的集合
一个会话可包含一个或多个进程组,但只能有一个前台进程组,其它的是后台进程组;每个会话都有一个会话首领(leader),即创建会话的进程
4 进程间通信 IPC
进程间通信 interprocess communication,简称 IPC,指两个进程之间的通信
进程间通信的本质 : 由 OS 参与,提供一份所有进程都可以访问的公共资源
公共资源包括: 内存块、队列、文件等,所以就出现了多种不同的进程间通信的方法
4.1 管道 pipe
- 匿名管道
匿名管道只能用于 父子进程 或者 具有“血缘关系”的进程之间的通信。
管道是一种单向通信的方法,一个进行向管道写入数据、另一个进程从管道读取数据
管道中的数据 并不存在于磁盘中,是存放在内存中,每一个管道会产生两个文件描述符,用来一读一写
- 命名管道
命名管道文件存在文件系统中,管道文件有自己的名字,可以向管道中读写数据。所以,命名管道可以作为同一台主机上的任意进程之间进行通信
4.2 信号
信号是事件发生时对进程的通知机制,信号的目的是用来通信的,当发生某种情况下,通过信号将情况“告知”相应的进程,从而达到同步、通信的目的
1、硬件发生异常,即硬件检测到错误条件并通知内核,随即再由内核发送相应的信号给相关进程
2、终端下输入了能够产生信号的特殊字符
CTRL + C 产生中断信号(SIGINT)
CTRL + Z 产生暂停信号(SIGCONT)
3、kill()系统调用可将任意信号发送给另一个进程或进程组
4、发生了软件事件,即当检测到某种软件条件已经发生,
进程所设置的定时器已经超时、进程执行的 CPU 时间超限、进程的某个子进程退出等等情况)
信号的处理方式
1、忽略信号。当信号到达进程后,有两种信号却决不能被忽略,它们是 SIGKILL 和 SIGSTOP
2、捕获信号。当信号到达进程后,执行预先绑定好的信号处理函数。
为了做到这一点,要通知内核在某种信号发生时,执行用户自定义的处理函数
3、执行系统默认操作。进程不对该信号事件作出处理,而是交由系统进行处理
每一种信号都会有其对应的系统默认的处理方式, 对大多数信号来说,系统默认的处理方式就是终止该进程
最后
以上就是欣慰烧鹅为你收集整理的Linux 基础进程的全部内容,希望文章能够帮你解决Linux 基础进程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复