背景---创建子进程
进程的启动路径==当前工作路径==创建新文件/子进程 的默认路径
修改当前进程的工作目录 == 修改创建新文件/子进程 的默认路径wLA7Pwi.Ec3:zFm
#include <stdio.h>//必备头文件
#include <sys/types.h>//getpid
#include <unistd.h>//sleep, chdir, getpid需要
int main()
{
chdir("/home/whb/111");//修改当前进程的工作目录
FILE *fp = fopen("log.txt", "w");//打开文件
(void)fp; // ignor warning 忽略警告(创建一个指针没使用时, 会报警告)
fclose(fp);//关闭文件
while(1)
{
printf("I am a process, pid: %d\n", getpid());
sleep(1);
}
return 0;
}
1. 进程状态
1.1. 直接谈论Linux的进程状态
1.1.1. 一个进程中的状态属性(修改等)举例
1.1.2. 进程的状态 (属性值本身是个宏)
static const char * const task_state_array[] = {
"R (running)", /* 0 */ //在CPU运行/队列
"S (sleeping)", /* 1 */ //浅休眠
"D (disk sleep)", /* 2 */ //深休眠(磁盘休眠)
"T (stopped)", /* 4 */ //暂停
"t (tracing stop)", /* 8 */ //暂停
"X (dead)", /* 16 */ //终止/释放
"Z (zombie)", /* 32 */ //僵尸
};
1.1.3. S+ 和 S的区别, +说明在后台, 不带+说明在前台
在Linux中,可以将进程分为前台进程和后台进程,它们的区别在于与终端的交互方式和执行状态。
前台进程:会有+
前台进程是当前正在与用户交互的进程,它会占用终端的输入和输出。
当用户在终端启动一个程序时,该程序通常成为前台进程,用户可以看到程序的输出,并且可以与程序进行交互。
前台进程会阻塞终端,直到该进程执行完毕或者暂停。
用户可以通过按下Ctrl + C来中断前台进程的执行。
后台进程:没有+
后台进程是在后台执行的进程,不会占用终端的输入和输出。
用户可以在命令行中在执行命令后面加上&符号,将进程放入后台执行。
后台进程不会阻塞终端,用户可以继续输入其他命令。
用户可以使用命令bg将一个前台进程转为后台进程,或者使用命令jobs查看当前所有的作业(包括前台和后台)。
使用kill 进程ID命令关闭对应的后台进程,比如kill 1234
1.1.4. 进程状态R, S的验证
vim中底行模式, 后者替换前者, :%s/原名称/替换后的名称
testStatus:testStatus.c
gcc -o $@ $^ -g
.PHONY:clean #.PHONY伪目标让clean总是被执行(因为如果是生产文件相关的命令, 源文件没有被再次修改时, 是不允许重复生成的)
clean:
rm -f testStatus
/**************************************************************/
验证
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
while(1)
{
printf("I am a process, pid: %d\n", getpid());
}
return 0;
}
while :; do ps ajx | head -1 && ps ajx | grep testStatus | grep -v grep; sleep 1; done //死循环, 每轮执行后暂停1秒; //ps ajx显示当前系统中的进程; -v是反向过滤
因为cpu速度非常快, 相对的显示器就显得很慢, CPU运行完一行printf代码, 把需要显示的内容先传输到内存, 在传给显示器; 假设CPU运行一次printf只用1纳秒, 但后面传给内存, 显示器需要100纳秒, 那么进程被cpu执行了1次printf后, 把结果传给内存, 再使用显示器(正在打印第一次printf的内容)资源几十纳秒, 在显示器显示一次结果期间, cpu可能已经执行了几十次, 传给内存缓冲区几十个结果, 都在等待显示器资源就绪. 所以进程的状态大部分都是S; 被CPU运行的过程叫执行过程R, 等待显示器资源得过程叫休眠(S)(不运行)
因为CPU与显示器的速度差距太大, 所以显得进程总是在等待显示器资源
R 是运行状态, 它表明进程要么是在运行中, 要么在运行队列里
S 是休眠/等待状态, 等待其它(CPU外)资源就绪 / 等待特定事件的完成(这里的睡眠有时候也叫做可中断睡眠(可以被ctrl+c 或 kill 终断)(interruptible sleep)
1.1.5. 状态T/t(追踪暂停)
1.1.5.1. kill指令—向进程发送信号, kill -l 进程的信号(都是宏)
9 SIGKILL是杀掉进程, 19 SIGSTOP是暂停进程, 18 SIGCONT继续进程, signal信号
调试时断点停止, 也是暂停, 等待进一步被唤醒
在Linux系统中,当一个进程接收到SIGSTOP信号时,它会被暂停(停止)执行,进入停止状态。在这种状态下,进程的执行被暂时挂起,不会继续执行,也不会被调度到CPU上运行。
停止状态下的进程不会消耗CPU资源,也不会响应任何信号,直到接收到SIGCONT信号后才会继续执行。停止状态的进程可以通过ps/pgrep命令或者类似的工具查看,通常会显示为T状态。
要将一个进程从停止状态恢复到运行状态,可以向该进程发送SIGCONT信号。这样进程就会从停止状态恢复到运行状态,继续执行kill指令—向进程发送信号
//在Linux系统中,kill指令用于向进程发送信号。通过kill指令,可以向指定的进程发送不同的信号,从而影响进程的行为。常用的kill指令格式如下:
kill [options] <PID> //选项前最好加-, 否则OS可能会识别错误(kill 19识别成kill -9)
其中,<PID>是要发送信号的进程的进程ID(Process ID)。可以使用ps指令或者pgrep指令来查找进程的进程ID。
- 9:发送SIGKILL信号,强制终止进程。
- 15(或不加选项):发送SIGTERM信号,请求进程正常终止。
kill -l是用来列出系统支持的信号列表的命令
- 19 SIGSTOP(编号为19):发送SIGSTOP信号会使进程停止执行,进程将被挂起,直到接收到SIGCONT信号继续执行。SIGSTOP信号不能被捕获、忽略或阻塞,是一种强制停止进程的信号。
- 18 SIGCONT(编号为18):发送SIGCONT信号会使之前被停止的进程继续执行。这个信号用于恢复被SIGSTOP或者类似信号暂停的进程的执行。
1.1.6. 磁盘睡眠D(Linux特有)
磁盘休眠状态
也是阻塞状态。D磁盘休眠状态(Disk sleep)是Linux系统中的一种进程状态,有时也称为不可中断睡眠状态(uninterruptible sleep)。进程进入这种状态通常是因为正在等待某些IO操作的完成,比如磁盘读写操作,网络请求等。在D状态下的进程是无法被中断或者唤醒的,直到IO操作完成为止。
- 问题:
当系统内存压力非常大时,操作系统有权利根据一定的策略选择杀死一些进程以释放内存空间,从而维持系统的稳定性和可用性。这种行为通常称为"内存压力控制"或"内存压缩",它是Linux内核中的一个重要特性之一。
有些进程正在等待1GB数据写入磁盘是否成功的返回信息, 但OS看他闲, 就直接把他释放了, 等到磁盘写入成功/失败后, 想返回信息, 发现进程没了, 磁盘只能继续给别的进程工作; 这1GB数据就全丢了, 没人知道它在哪, 是否存在了,
- 解决:
引入D状态, 处于D状态的进程不可被中断 / kill
- 消除D状态的方法: 进程自己醒, 关机/断电