ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【Linux】从零开始认识进程 — 中上篇 [打印本页]

作者: 卖不甜枣    时间: 2024-8-11 18:03
标题: 【Linux】从零开始认识进程 — 中上篇

今天我们继承学习进程,首先送给各人一句话:
如果痛恨所处的黑暗,请你成为你想要的光。 —— 顾城

  
1 认识进程收尾

进程的路径是可以改变的, 每个进程在启动的时候,会记录自己当前在哪个路径下启动。
我们可以使用fopen ("log.txt",“w”)来进利用用,该函数会在路径下创建一个新文件log.txt。即可验证进程所处路径:
  1.   1 #include<stdio.h>
  2.   2
  3.   3 int main(){
  4.   4   FILE* fp = fopen("log.txt","w");
  5.   5   (void)fp;//防止报错
  6.   6                                                                                                                                                                              
  7.   7   return 0;
  8.   8 }
复制代码
我们编译运行之后,就可以发现当前路径下创建了一个新文件log.txt。

那我们可不可以改变一下进程的路径呢,固然可以,使用int chdir(const char* path)就可以实现改变进程路径的功能.
我们来试一试,通用通过代码来测试一下:
  1.   1 #include<stdio.h>
  2.   2 #include<unistd.h>
  3.   3 #include<sys/types.h>
  4.   4
  5.   5 int main(){
  6.   6
  7.   7   chdir("/home/jlx/lesson12");
  8.   8
  9.   9   FILE* fp = fopen("log.txt","w");
  10. 10   (void)fp;
  11. 11
  12. 12   while(1){
  13. 13     printf("I am a process,pid: %d\n",getpid());                                                                                                                              
  14. 14     sleep(1);
  15. 15   }
  16. 16
  17. 17   return 0;
  18. 18 }
复制代码
接下来我们来观察一下:

在lesson12路径下也成功创建了新文件log.txt。所以我可以更改进程的工作路径,默认是在可执行程序的路径下。
2 进程状态

2.1 谈谈Linux进程状态

进程状态是task_struct内部的一个属性,int status就是一个代表状态的数字。
看看Linux内核源代码怎么说:
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在
Linux内核里,进程偶然候也叫做任务)。下面的状态在kernel源代码里界说:
  1. /*
  2. * The task state array is a strange "bitmap" of
  3. * reasons to sleep. Thus "running" is zero, and
  4. * you can test for combinations of others with
  5. * simple bit tests.
  6. */
  7. static const char * const task_state_array[] = {
  8. "R (running)", /* 0 */
  9. "S (sleeping)", /* 1 */
  10. "D (disk sleep)", /* 2 */
  11. "T (stopped)", /* 4 */
  12. "t (tracing stop)", /* 8 */
  13. "X (dead)", /* 16 */
  14. "Z (zombie)", /* 32 */
  15. };
复制代码

接下来我们来验证一下这些状态(D状态无法验证,X状态无法验证)
R 、T、 D状态

写个程序来进行测试:
  1.   1 #include<stdio.h>
  2.   2 #include<sys/types.h>
  3.   3 #include<unistd.h>
  4.   4
  5.   5 int main()
  6.   6 {
  7.   7   while(1)
  8.   8   {                                                                                
  9.   9     printf("I am a process,pid : %d\n",getpid());//注意这里没有写sleep函数
  10. 10   }
  11. 11
  12. 12   return 0;
  13. 13 }
复制代码
使用while : ;do ps ajx | head -1&& ps ajx | grep testStatus |grep -v grep ;sleep 1 ;done指令进行实时监控:

可以看到我们右边的可执行程序同等在运行,但是在左边的监控中,却发现是S+状态???这是为什么怎么会是休眠状态(sleep),显着一直在运行啊!?
我们来把printf去掉,再来看看怎么样
  1.   1 #include<stdio.h>
  2.   2 #include<sys/types.h>
  3.   3 #include<unistd.h>
  4.   4
  5.   5 int main()
  6.   6 {
  7.   7   while(1)
  8.   8   {                                                                                
  9.   9     //printf("I am a process,pid : %d\n",getpid());//注意这里没有写sleep函数
  10. 10   }
  11. 11
  12. 12   return 0;
  13. 13 }
复制代码
来看运行的效果:

唉?!怎么现在成了R+状态了???怎么现在就是运行状态了???
这个问题到底是怎么一回事儿???
其实这与printf有关,printf的本质是往外设显示器上打印,但是进程是在云服务的cpu上运行的。根据冯诺依曼体系结构,外设的处置惩罚速度要远远小于cpu,所以在显示器的打印过程中,cpu就在等待显示器装备打印停当(也变相证明了cpu运行速度比显示器快的多的多的多!!!)

通过刚刚的证明,说明了:
在来看暂停状态 : T(让进程先暂停,等待被唤醒)
使用 kill 下令可以进程发信号,kill具有以下信号(宏界说信号):
  1. 1) SIGHUP         2) SIGINT         3) SIGQUIT         4) SIGILL         5) SIGTRAP
  2. 6) SIGABRT         7) SIGBUS         8) SIGFPE         9) SIGKILL        10) SIGUSR1
  3. 11) SIGSEGV        12) SIGUSR2        13) SIGPIPE        14) SIGALRM        15) SIGTERM
  4. 16) SIGSTKFLT        17) SIGCHLD        18) SIGCONT        19) SIGSTOP        20) SIGTSTP
  5. 21) SIGTTIN        22) SIGTTOU        23) SIGURG        24) SIGXCPU        25) SIGXFSZ
  6. 26) SIGVTALRM        27) SIGPROF        28) SIGWINCH        29) SIGIO        30) SIGPWR
  7. 31) SIGSYS        34) SIGRTMIN        35) SIGRTMIN+1        36) SIGRTMIN+2        37) SIGRTMIN+3
  8. 38) SIGRTMIN+4        39) SIGRTMIN+5        40) SIGRTMIN+6        41) SIGRTMIN+7        42) SIGRTMIN+8
  9. 43) SIGRTMIN+9        44) SIGRTMIN+10        45) SIGRTMIN+11        46) SIGRTMIN+12        47) SIGRTMIN+13
  10. 48) SIGRTMIN+14        49) SIGRTMIN+15        50) SIGRTMAX-14        51) SIGRTMAX-13        52) SIGRTMAX-12
  11. 53) SIGRTMAX-11        54) SIGRTMAX-10        55) SIGRTMAX-9        56) SIGRTMAX-8        57) SIGRTMAX-7
  12. 58) SIGRTMAX-6        59) SIGRTMAX-5        60) SIGRTMAX-4        61) SIGRTMAX-3        62) SIGRTMAX-2
  13. 63) SIGRTMAX-1        64) SIGRTMAX       
复制代码
此中的 -19 可以完成暂停 -18 可以让暂停状态继承运行。
来看演示:

如许直观就可以看到暂停状态了。
这个 t 暂停状态多在gdb调试里常见,我们俗称的断点就是做到使进程暂停的作用。即调试暂停
感兴趣可以自行查看哦。
D 状态
这个状态也叫也叫不可中断睡眠状态,是内存为了掩护数据不得不接纳的删除进程操纵,一般不会遇见。
2.2 僵尸进程和孤儿进程

接下来我们来了解僵尸进程和孤儿进程。
Z(zombie)-僵尸进程


这个状态类似有人受害,被抛尸荒原,警察一定会封锁现场,法医进行甄别,最后是家属来准备后事。
所以进程也需要有人来把他收走,准备后事。
我们写一段代码来看看:
  1.   1 #include<stdio.h>
  2.   2 #include<sys/types.h>
  3.   3 #include<unistd.h>
  4.   4
  5.   5 int main()
  6.   6 {
  7.   7   pid_t id = fork();
  8.   8   if(id == 0)
  9.   9   {
  10. 10     int cnt = 5;
  11. 11     while(cnt--)
  12. 12     {
  13. 13       printf("I am child,cnt: %d ,pid: %d \n",cnt,getpid());                       
  14. 14       sleep(1);
  15. 15     }
  16. 16   }
  17. 17   else
  18. 18   {
  19. 19     while(1)
  20. 20     {
  21. 21       printf("I am parent,running always,pid: %d\n",getpid());
  22. 22       sleep(1);
  23. 23     }
  24. 24   }
  25. 25 }
复制代码
这个代码子进程运行五次就会停止,让我们看看效果:

当cnt小于0时,就结束了进程,于是子进程就成为了僵尸进程。依然就要PID但是不在进行运行。
此中的<defunct>表示被抛弃的,不运行的。
僵尸进程就是:已经运行完毕,但是需要维持自己的退出信息,在自己的进程task_struct中记录自己的信息,将来让父进程来进行读取。如果没有父进程进行读取,僵尸进程会一直存在(会引起内存泄漏问题)
僵尸进程危害

孤儿进程

再来看孤儿进程(与僵尸进程相反,孤儿进程是父进程运行完毕了):

这个就类似孤儿,我们写代码来测试一下:
  1.   1 #include<stdio.h>
  2.   2 #include<sys/types.h>
  3.   3 #include<unistd.h>
  4.   4
  5.   5 int main()
  6.   6 {
  7.   7   pid_t id = fork();
  8.   8   if(id == 0)
  9.   9   {
  10. 10     
  11. 11     while(1)
  12. 12     {
  13. 13       printf("I am child,running always,pid: %d \n",getpid());
  14. 14       sleep(1);                                 
  15. 15     }
  16. 16   }
  17. 17   else
  18. 18   {
  19. 19     int cnt = 5;
  20. 20     while(cnt--)
  21. 21     {
  22. 22       printf("I am parent,cnt:%d,pid: %d\n",cnt,getpid());                        
  23. 23       sleep(1);                                                                 
  24. 24     }                                                                           
  25. 25   }                                                                                                                                                      
  26. 26 }                                                                              
复制代码
这个代码父进程运行五次就会停止,让我们看看效果:

如许子进程就变成了孤儿进程STAT。
孤儿进程在运行结束后,会被1号进程(操纵体系本身)进行领养,保证子进程正常被接纳!
2.3 浅谈进程的阻塞、挂起和运行


这个是操纵体系的宏观理论(指导思想),对于任意一门操纵体系都实用!!!
送给我们一句话:

如果痛恨所处的黑暗,请你成为你想要的光。 —— 顾城
Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4