建视频网站模板,企业网站上的二维码怎么获得,网页设计技术论文范文,广州seo技术培训文章目录 进程状态进程排队进程的状态#xff08;运行#xff0c;阻塞#xff0c;挂起#xff09;进程的七个状态 孤儿进程 进程状态
进程 task_struct 可执行程序 进程不是一 直在运行的#xff0c;可能在等待软硬件资源#xff0c;比如scanf后#xff0c;程序停止运… 文章目录 进程状态进程排队进程的状态运行阻塞挂起进程的七个状态 孤儿进程 进程状态
进程 task_struct 可执行程序 进程不是一 直在运行的可能在等待软硬件资源比如scanf后程序停止运行了在等待用户输入。进程放在CPU上也不是一直在运行的。时间片进程在CPU上的时间过了就会被拿下。
进程排队
先简单看看进程排队 所谓的进程排队一定是在等待某种资源排队是进程的PCB(task_struct)在排队而不是进程的可执行程序在排队。 一个task_struct进程的PCB可以被连入多种数据结构中 在Linux内核中每一个进程的PCB不是连入到单链表中的而是连入到双链表的队列可以用链表实现这个结构和书本上学习的双链表结构一样的但用法不同而已请看图解 图一 注释如果像下图这样管理PCB的话(也就是每一个进程PCB中包含两个指针但是这样只能连入一到一个数据结构中如果想要连入到多种数据结构中必须加指针浪费空间并且难维护)所以这种结构是不合适的。 图二 注解每一个进程的PCB中包含特殊的结构体然后将这个结构体指针放入双链表中进行管理这样就可以通过这个结构体指针找到进程的PCB这个结构体指针也可以连入多种数据结构中。利用struct listnode在对应进程的PCB中偏移量计算PCB的地址(task_struct*)(n-((task_struct)0- n。如果PCB中存在很多个特殊的结构体就可以将PCB连入到很多不用的数据结构中进行管理。
进程的状态运行阻塞挂起
所谓的状态其实就是一个整型变量在task_struct里面的一个整型变量
状态决定了什么 状态决定了下一步的后续动作。
一个CPU一个运行队列。 如简图 运行状态一个进程的PCB在CPU的运行队列上不一定正在运行把该进程的状态成为运行状态 阻塞状态 每一个设备为了操作系统能够管理。都会被先描述后组织。将设备用一个结构体描述结构体里面可能会包含设备类型状态以及当前设备的等待队列等。 当一个进程在等待软硬件资源的时候如果资源没有就绪例如scanf时操作系统会将该进程PCB从与逆行队列拿下来状态由运行改为阻塞连入到等待的资源提供的的等待队列中等待资源
其中状态的变迁引起的是PCB会被OS变迁到不同的队列中。
挂起状态 前提当计算机资源已经很吃紧了 阻塞挂起已经很吃紧了但是有一些进程暂时不会被调度操作系统会将该进程的代码与数据写入到外设磁盘中去也就是腾空间。磁盘有一个固定的区域叫做swap分区是用来给操作系统在资源紧张的时候用来和磁盘进行数据的唤入与唤出 注意进程的PCB不会被唤入将数据拷贝到外设唤出将数据从外设唤入到内存。 创建一个进程的时候先创建进程的对应的内核数据结构PCB再将代码与数据加载到内存可以一部分一部分的加载按需加载 。
进程的七个状态
static const char * const task_state_array[] {
R (running), /* 0 */
S (sleeping), /* 1 */
D (disk sleep), /* 2 */
T (stopped), /* 4 */
t (tracing stop), /* 8 */
X (dead), /* 16 */
Z (zombie), /* 32 */
}; R运行状态running: 并不意味着进程一定在运行中它表明进程要么是在运行中要么在运行队列里。S睡眠状态sleeping): 意味着进程在等待事件完成这里的睡眠有时候也叫做可中断睡眠阻塞状态。crtlc可以终止进程。D磁盘休眠状态Disk sleep,有时候也叫不可中断睡眠状态uninterruptible sleep在这个状态的进程通常会等待IO的结束。阻塞状态crtlc不可以终止进程。T停止状态stopped 可以通过发送 SIGSTOP 信号给进程来停止T进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。t停止状态在调试的时候可以看见。Zzombine僵尸状态。X死亡状态dead这个状态只是一个返回状态你不会在任务列表里看到这个状态。
Linux进程状态转换图
测试使用指令
# ps ajx | head -1 ps ajx | grep myprocess测试代码1 1 #includestdio.h2 #includestdlib.h3 #includeunistd.h4 5 int main()6 {7 while(1)8 {9 printf(i am a proces id:%d\n,getpid());10 sleep(1); 11 }12 return 0;13 }
运行结果
问题为什么我的代码在运行但是确是S状态呢 答因为CPU执行你的代码非常快剩下的还执行了sleep函数导致该进程大多时间处于sleep状态只有很少量的时间被调度了一次导致很难观察到运行状态。
测试代码2 1 #includestdio.h2 #includestdlib.h3 #includeunistd.h4 5 int main()6 {7 while(1)8 {9 printf(i am a proces id:%d\n,getpid());10 //sleep(1); 11 }12 return 0;13 }
运行结果
问题为什么我的代码将sleep注释掉了再运行但是确还是S状态呢 代码中使用的printf函数是要访问外设的但是要访问这个设备这个设备的资源不一定准备就绪了但是CPU的执行速度很快但是硬件的速度很慢导致大部分时间也是在等待状态的。
测试代码3 1 #includestdio.h2 #includestdlib.h3 #includeunistd.h4 5 int main()6 {7 while(1)8 {9 //printf(i am a proces id:%d\n,getpid());10 //sleep(1); 11 }12 return 0;13 }运行结果 为什么状态后有呢比如S 后面带有说明是前台进程没有代表为后台进程 例如
指令前台进程变为后台进程
# ./myprocess 可以将前台进程变为后台进程后台进程使用键盘ctrlc不能杀掉只能用命令kill -9 杀掉
例如 测试代码 1 #includestdio.h2 #includestdlib.h3 #includeunistd.h4 5 int main()6 {7 while(1)8 {9 printf(i am a proces id:%d\n,getpid());10 sleep(1); 11 }12 return 0;13 }T状态的测试
测试代码 1 #includestdio.h2 #includestdlib.h3 #includeunistd.h4 5 int main()6 {7 while(1)8 {9 printf(i am a proces id:%d\n,getpid());10 sleep(1); 11 }12 return 0;13 }运行结果 T状态让进程处于暂停状态。 t状态的测试 当我们调试代码的时候在每次单步执行的时候程序会处于t状态停止状态
示例
Z状态僵尸状态当一个进程退出后但是该进程的状态需要自己维持住供上层读取。也就是进程从退出到资源被清理的这个时间段进程所处于的状态。
当一个进程退出过后代码和数据可以被直接释放因为已经没有用了但是当前进程所对应的PCB还不能被释放里面还有记录进程的退出信息是为了让系统或者其他进程能够读取到该进程的的退出信息进而执行下一步动作。只有该数据被拿走过后这个进程才是真正的死亡状态。PCB才会被清理释放。如果父进程不读取子进程的退出信息僵尸状态的进程会一直存在task_struct对象也会一直存在都是要暂用内存的会有内存泄漏。在Linux系统中所有的进程退出后都是Z状态。只有被别人读取完成后才会变为X状态。
测试代码 1 #includestdio.h2 #includestdlib.h3 #includeunistd.h 45 int main()6 {7 pid_t id fork();8 if(id0) 9 { 10 int cnt 5; 11 while(cnt) 12 { 13 printf(i is child id:%d pid:%d\n,getpid(),getppid());14 sleep(1);15 cnt--;16 } 17 exit(0); //让子进程直接退出 18 }19 //father 20 while(1) 21 {22 printf(i is father id:%d pid:%d\n,getpid(),getppid());23 sleep(1);24 }25 return 0;26 }结果5秒过后子进程状态变为Z僵尸状态因为进程退出后退出信息你没有被读取怎么读取后续文章再给出。
孤儿进程
如果一个进程的父进程已经退出但是子进程还没有退出这个子进程就被叫做孤儿进程。 这是孤儿进程会变为后台进程只有不能ctrlc杀掉可以通过kill命令。
这个进程会被1号进程操作系统所领养如果不被领养就变成没有主的进程当程序退出时就会一直为僵尸进程就会一直暂用资源空间所以孤儿进程会被1号进程领养这样该进程的资源还可以被操作系统所回收。
测试代码 1 #includestdio.h2 #includestdlib.h3 #includeunistd.h 4 5 int main()6 {7 pid_t id fork();8 if(id0)9 {10 int cnt 50;11 while(cnt)12 {13 printf(i is child id:%d pid:%d\n,getpid(),getppi d());14 sleep(1);15 cnt--;16 }17 exit(0); //让子进程直接退出18 }19 //father20 int cnt 5;21 while(cnt)22 {23 printf(i is father id:%d pid:%d\n,getpid(),getppid ());24 sleep(1);25 cnt--;26 }27 printf(父进程退出\n);28 return 0;29 }