【进程概念】启动进程 | 查看进程 | 创建进程

目录

启动进程

查看进程

方法1:/proc

方法2:查看脚本

​方法3:系统调用获取进程标示符❗❗

终止进程 

创建进程(主fork)

🙂查看父子进程的pid 

🙂进程创建/执行/终止

🙂多次重新启动进程查看pid和ppid

​🙂系统调用函数fork创建子进程 

🙂why❓fork有两个返回值

🙂父子进程执行不一样的代码 

进程的当前工作路径 


从本篇开始陆续介绍Linux中进程的task_struct本省内部的属性。 

启动进程

  • ./ 本质上就是让系统创建进程并运行。
  • myprocess.c是C语言源代码
  • myprocess是可执行文件(gcc/g++)
  • 可执行的程序的可执行文件在磁盘上
  • ./运行程序:把可执行程序加载到内存上,OS创建task_struct,进入排队,等待调度。
  • 启动程序:就是让系统创建进程并运行。
  • 我们自己写的代码形成的可执行程序 == 系统指令(都是可执行程序) == 可执行文件。
  • 在Linux中运行的大部分指令操作,本质都是运行程序。

  • 在Linux中启动进程一般make(shell命令行)

  • 在windows启动进程双击(图形化界面)

【Makefile】 

  1 myprocess:myprocess.c
  2     gcc -o $@ $^ -g
  3 .PHONY:clean
  4 clean:
  5     rm -f myprocess 

【myprocess.c】 

  1 #include<stdio.h>
  2 #include<unistd.h>//sleep函数包含的头文件
  3 int main()
  4 {
  5     //让这个进程持续运行不停止
  6     while(1)
  7     {
  8         printf("I am a process!\n");
  9         sleep(1);
 10     }
 11     return 0;                                                                                                
 12 }
 ./myprocess

I am a process!
I am a process!
I am a process!
I am a process!
//之后myprocess已经是一个进程

【在/usr/bin/find目录下查看的可执行程序】

file /usr/bin/find

查看进程

 怎么查看进程呢?父进程,子进程?

  • 进程的信息可以通过 /proc 系统文件夹查看
  • 系统调用获取进程的标识符
  • 查看脚本

方法1:/proc

如:要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹。

ls /proc/1
ls /proc/

方法2:查看脚本

大多数进程信息同样可以使用top和ps这些用户级工具来获取。

  • ps查看当前系统的进程
  • axj显示进程的详细信息(可以打乱顺序写)
  • ps axj是用户级的工具,可以行输出消息
  • grep也是一个可执行程序
  • grep可以把数据按照 行过滤的方式输出

ps axj | grep myprocess :grep把得到的进程信息数据,按照行过滤的方式,凡是包含myprocess的关键字全部提取出来。


  • head n查看前n行的信息

ps axj | head -1 查看进程信息的属性信息


  • grep -v 关键字 就是除了显示除了关键字以外的其他行信息
  • -v反向过滤
  • 不需要查看grep的进程信息,举例很混乱。

ps axj | grep -v grep


  • && 一起查看,两个命令同时进程
  • | 管道
  • 查阅出来的信息也可能含有grep的进程信息,因为grep也是一个进程。grep这个进程本省也携带了过滤myprocess的这个关键字。

  • 周期性循环查看进程脚本
  •  while :; do ps axj | head -1 && ps axj | grep -v grep | grep process; sleep 1; done
  • 清晰的看到进程的创建,执行,中止,状态这一整个连贯操作。
ps axj | grep myprocess
ps axj | head -1
ps axj | head -1 && ps axj | grep 关键字
ps axj | head -1 && ps axj | grep -v 关键字 | grep 关键字
ps axj | head -1 && ps axj | grep -v grep | grep process
//循环查看脚本
while :; do ps axj | head -1 && ps axj | grep -v grep | grep process; sleep 1; done

 方法3:系统调用获取进程标示符❗❗

  • 进程的pid:每一个进程都要有自己的唯一标识符,叫做进程pid
  • 进程的ppid(子进程的父进程的pid)
  • pid:process id 表示进程的唯一标识符
  • ppid:process parent id

  • pid和ppid同理
  • pid的类型是unsigned int,无符号整数被操作系统封装成pid_t的类型
  • pid是一个无符号整型的变量(unsigned int)
  • 每一个进程都有task_struct,每个进程间的task_struct怎么区分,用pid❗❗
  • Linux中PCB就是task_struct,进程 == 任务task
  • 用户想要知道一个进程的pid,是不能够直接到操作系统的内核数据结构中去查询的PCB的pid,需要使用操作系统提供的"系统调用接口"去查询

pid的查看

  • 使用man指令去查询getpid 和getppid:man pid 
  • ❓若查询不到,请安装man命令的一个man-pages安装包
  • 安装查看:yum install man-pages(安装的时候只能用超级管理员root安装)
  • 系统调用函数getpid查看子进程的pid
  • 用getppid查看子进程的ppid == 父进程pid     
  • #include <sys/types.h>
  • #include <unistd.h>

理解:当代码预处理,编译,汇编,链接形成可执行程序的文件的时候是在磁盘中存放,这个时候还不是进程,也没有运行一行代码。只有可执行程序加载到内存,OS创建进程启动进程调度进程的时候。进程启动起来,系统调用函数才会获得PCB的pid。

  • 操作系统OS没有PCB,操作系统内核有定期的任务。比如刷新,内存管理之类这些有PCB,操作系统OS本身不需要PCB
yum install man-pages //记得指令提权
man pid
man 2 pid 


【用系统调用函数查看进程的pid】

  1 #include<stdio.h>
  2 #include <sys/types.h>
  3 #include <unistd.h>
  4 
  5 int main()
  6 {
  7     pid_t id=getpid();
  8     //让这个进程持续运行不停止
  9     while(1)
 10     {
 11         printf("I am a process!,pid=%d\n",id);     
 12         sleep(1);
 13     }
 14     return 0;
 15 }

终止进程 

  • ctrl+c就是在用户层面终止进程
  • kill -9 pid 可以用来直接杀掉进程 

创建进程(主fork)

进程创建的代码方式

(这里讲解重点在操作,轻微原理。后面会重谈进程的创建以及其他方法)

  • pid_t getpid(void);获得当前进程的pid
  • pid_t getppid(void);获得当前进程的父进程的pid
  • 父进程VS子进程
  1. bash是父进程,进程创建进程
  2. 系统调用函数创建进程

🙂查看父子进程的pid 

  1 #include<stdio.h>
  2 #include <sys/types.h>
  3 #include <unistd.h>
  4 
  5 int main()
  6 {
  7     pid_t id=getpid();
  8     pid_t parentid=getppid();
  9     //让这个进程持续运行不停止
 10     while(1)
 11     {
 12         printf("I am a process!,pid=%d,ppid:%d\n",id,parentid);                      
 13         sleep(1);                                                     
 14     }                                               
 15     return 0;                                       
 16 } 

🙂进程创建/执行/终止

while :; do ps axj | head -1 && ps axj | grep -v grep | grep process; sleep 1; done

🙂多次重新启动进程查看pid和ppid

❓我们发现每次重新启动进程,进程的pid都要改变,但是进程的父进程pid都不改变。

❓查询父子进程属性信息:发现都有bash进程

  • 进程每次启动,对应的pid都不一样是正常的
  • 经过验证,我们创建的进程的父进程就是bash
  • bash是父进程,是实习生,是李婆,命令行解释器。
  • ❗所以进程可以创建进程。
ps axj | head -1 && ps axj | grep -v grep | grep 13185//查询父进程
ps axj | head -1 && ps axj | grep -v grep | grep 12345 //查询子进程随机一个

🙂系统调用函数fork创建子进程 

  • 创建一个进程,OS内多了进程,多了进程的PCB,内存多了进程的代码和数据。
  • 用户想要创建进程,就要创建内核数据结构,用户是没有权力对操作系统内部的内核数据结构等做增删查改的。
  • 所以,用户只能使用OS提供的系统调用函数来创建子进程。
  • fork:分支,叉子。创建子进程。
  • man fork
  • 头文件:  #include <unistd.h>
  • 返回值有两个类型都是pid_t
  • 可以接收返回值,也可以不接收。

fork创建子进程的脑中图,理解记忆❗

  • 在fork创建了子进程,是由父子进程分别都要执行后序代码,它们共享一份代码。
  • 创建一个进程,本质是系统中多一个进程,那么内存也会多一份代码和数据。
  • 父进程的代码和数据是从磁盘中加载过来的
  • 父进程的PBC也是OS动态创建的

❓子进程的代码和数据,PBC呢?

  • 子进程的代码和数据也可以从磁盘再加载一份到内存(下个博文进程控制会讲)
  • 在fork这里默认子进程的代码和数据是继承父进程的
  • 数据也是继承的吗❓

所以,fork()之后,父子进程代码共享。理论上,子进程是在fork之后共享了父进程的代码和数据,OS才动态创建了子进程的PCB

  1 #include<stdio.h>
  2 #include <sys/types.h>
  3 #include <unistd.h>
  4 
  5 int main()
  6 {
  7     printf("process is running,only me!\n");//只有父进程
  8     sleep(3);
  9     fork();//创建子进程
 10     printf("hello linux\n");
 11     sleep(5);                                                                                   
 20     return 0;
 21 }

  1 #include<stdio.h>  
  2 #include <sys/types.h>  
  3 #include <unistd.h>  
  4   
  5 int main()  
  6 {  
  7     pid_t id=getpid();  
  8     pid_t parentid=getppid();                                                                   
  9     printf("process is running,id=%d,parentid=%d\n",id,parentid);//只有父进程  
 10     sleep(3);                                                 
 11     fork();//创建子进程                                       
 12     printf("hello linux,id=%d,parentid=%d\n",id,parentid);    
 13     sleep(5);                                                                                                       
 22     return 0;                                                 
 23 }                                                             
~      

🙂why❓fork有两个返回值

🙂父子进程执行不一样的代码 

进程的当前工作路径 

🙂感谢大家的阅读,若有错误和不足,欢迎指正。 

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-03-24 07:32:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-24 07:32:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-24 07:32:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-24 07:32:02       18 阅读

热门阅读

  1. Linux: network:interrupt: python tool

    2024-03-24 07:32:02       17 阅读
  2. C# 编程语言中访问修饰符(access modifiers)

    2024-03-24 07:32:02       18 阅读
  3. SpringBoot 定时器@Scheduled的使用

    2024-03-24 07:32:02       16 阅读
  4. Wpf-自定义控件波纹Button

    2024-03-24 07:32:02       20 阅读
  5. 【大厂面试题购物车】通关代码

    2024-03-24 07:32:02       17 阅读
  6. C++常用的库

    2024-03-24 07:32:02       17 阅读
  7. 基于FPGA的UDP协议栈设计第六章_仲裁模块设计

    2024-03-24 07:32:02       16 阅读
  8. leetcode - 362. Design Hit Counter

    2024-03-24 07:32:02       18 阅读
  9. v-if 遇到 el-form 表单验证规则遇到的bug

    2024-03-24 07:32:02       19 阅读
  10. c语言:日期识别1

    2024-03-24 07:32:02       17 阅读