进程是程序运行的实例,有独立的4G地址空间,1G是内核战友,3G是私有内存空间,有自己的PID和PCB
1、进程的基本命令:
①ps命令
pid -->标记进程的(进程的身份证)
ps -aux :查看进程的信息
ps -ef :查看信息包含父进程的进程号 PPID
ps -ajx:可以查看 (父进程id 组id 会话id)
多个进程可以组成一个组,多个组可以组成一个会话,多个会话可以组成一个会话组。
./a.out & :将a.out在后台运行起来
Ctrl+z:将前台运行的进程暂停同时放到后台
bg 数字(这里的数字为你按Ctrl+Z的时候前面中括号
里面的数字):将后台暂停的进程在后台跑起来。
fg 数字 :将后台运行的进程拉到前台运行
man ps:
D uninterruptible sleep (usually IO) 不可中断睡眠
R running or runnable (on run queue) 运行
S interruptible sleep (waiting for an event to complete) 可中断睡眠
T stopped by job control signal 暂停
X dead (should never be seen) 死亡
Z defunct ("zombie") process, terminated but not reaped by its parent 僵尸
< high-priority (not nice to other users) 高优先级
N low-priority (nice to other users) 低优先级
L has pages locked into memory (for real-time and custom IO)
锁定到内存中
s is a session leader 会话组组长
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)多线程
+ is in the foreground process group 前台进程
D: 不可中断的静止
R: 正在执行中
S: 阻塞状态
T: 暂停执行
Z: 不存在但暂时无法消除
W: 没有足够的内存分页可分配
<: 高优先级的进程
N: 低优先级的进程
L: 有内存分页分配并锁在内存中
②top 动态显示进程的状态
shift + >翻页
shift + <
PR :PR=NI+20
NI:优先级 +19 - -20
值越小优先级越高
③nice 以指定优先级运行进程
sudo nice -n num ./可执行程序 :以优先级为num运行程序
④renice 运行进程优先级修改
sudo renice -n num PID
⑤kill 给进程发送信号
kill -l :查看linux中的信号
2) SIGINT ctrl+c
9) SIGKILL 杀死进程信号
19) SIGSTOP 暂停
2) SIGINT 3) SIGQUIT 退出进程 4) SIGILL结束进程
9) SIGKILL杀死(不可忽略) 10) SIGUSR1未定义功能
12) SIGUSR2未定义功能 13) SIGPIPE管道破裂 14) SIGALRM定时信号
17) SIGCHLD子进程状态改变给父进程发 19) SIGSTOP暂停(不可忽略)
SIGUSR1 SIGUSR2 未定默认功能信号
kill -信号编号 PID :给指定进程发送指定信号
killall a.out :杀死所有名字为a.out
2、进程相关的函数
进程的创建fork(2)
#include<unistd.h>
pid_t fork(void);
功能:创建一个子进程(新建进程为子进程,当前为父进程)
返回值:
成功:父进程中返回子进程的PID
子进程中返回0
失败:在父进程中返回-1,errno被设置
父进程创建子进程后,谁先执行不一定,由操作系统统一调度决定子进程继承了父进程的fd和image,fork采用的是写时复制技术,写的时候才复制PCB中与父进程不同的地方
例如我们这样创建,一个父进程创建多个子进程,看下代码
如果是让父进程创建子进程,子进程再次创建子进程呢
进程的终止return和exit
return用于结束当前运行的函数
exit(3)将中止整个进程,进程中所有的函数都结束
#include<stdlib.h>
void exit(int status);
参数:
status:给定的返回码,status&0377,0377其实就是二进制的低八位都是1传递给父进程
返回值:从不返回
注:_exit(2)函数与exit(3)函数的区别是它不刷新缓存区
取进程的返回值echo $?,返回值存放在?中
例如退出码是exit(321)
321: 00000000,00000000,00000001,01000001
0377:00000000,00000000,00000000,11111111
相&结果十进制即是65
echo $?会得到65
但如果退出码是负数,有符号的整数是以补码的形式存在的
因此要使用补码与0388进行与运算
注:还有一个vfork函数,与fork不同之处是vfork要求先执行子进程,并且父子进程共享数据段
遗言函数
进程在终止时才调用的函数,是main函数结束以后在调用的函数,在进程正常存在的情况下,向进程注册遗言函数
如何注册 atexit(3)、on_exit(3)
#include<stdlib.h>
int atexit(void(*function)(void));
功能:向进程注册遗言函数,进程终止时被调用
参数:
function:指针类型,4字节,遗言函数的入口地址
返回值:
成功:返回0
失败:返回非0
int on_exit(void(*function)(int,void*),void*arg);
功能:向进程注册遗言函数
参数:
function:遗言函数入口地址
arg :自定义传递给function的第二个参数
int类型代表状态码
void*类型用来存储arg
返回值:
成功返回0;
错误返回非0;
注:
遗言函数的注册顺序与调用顺序相反
同一函数可被注册多次,每次注册都会调用一次,子程序继承父进程的遗言函数
exec(3)家族中的其中一个函数调用成功,所有注册的遗言函数都会被移除,因为遗言函数放在就得代码段,被新的代码段覆盖了
看看遗言函数的代码实现