当前位置: 首页 > news >正文

Linux初识进程

文章目录

    • 进程的基本概念
    • 描述进程-PCB
    • task_ struct
    • 查看进程
    • 通过==系统调用==获取进程标示符
    • 通过系统调用创建进程-fork初识


进程的基本概念

课本概念:程序的⼀个执⾏实例,正在执⾏的程序等
内核观点:担当分配系统资源(CPU时间,内存)的实体。
当前:进程=内核数据结构(task_struct)+⾃⼰的程序代码和数据

描述进程-PCB

写在前面先描述再组织,是所有管理任务的核心。而操作系统管理进程的方式就是利用PCB对进程进行描述。

  • 进程信息被放在⼀个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
  • 课本上称之为PCB(process control block),Linux 操作系统下的PCB 是: task_struct
  • 在Linux 中描述进程的结构体叫做task_struct
  • task_struct 是Linux 内核的⼀种数据结构类型,它会被装载到RAM(内存)⾥并且包含着进程的信息。

task_ struct

在任何操作系统中都存在PCB,而在Linux系统下,将PCB具体称为task_ struct,其包括以下内容:

  • 标⽰符:描述本进程的唯⼀标⽰符,⽤来区别其他进程。
  • 状态:任务状态,退出代码,退出信号等。
  • 优先级:相对于其他进程的优先级。
  • 程序计数器:程序中即将被执⾏的下⼀条指令的地址。
  • 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
  • 上下⽂数据:进程执⾏时处理器的寄存器中的数据[休学例⼦,要加图CPU,寄存器。
  • I∕O状态信息:包括显⽰的I/O请求,分配给进程的I∕O设备和被进程使⽤的⽂件列表。
  • 记账信息:可能包括处理器时间总和,使⽤的时钟数总和,时间限制,记账号等。

查看进程

查看进程的两种方式:

  • 通过ps指令查询进程
ps ajx | grep processname

在这里插入图片描述

  • 可以使用分号或者&&连接两条语句,同时执行.

  • grep 带-v选项,不搜索本身

  • 通过/proc目录查看进程

ls /proc 

在这里插入图片描述
在这里插入图片描述

  • cwd表示当前当前的工作目录
  • exe表示进程对应的可执行文件的目录
  1. 杀死进程
kill -9 xxxx

在这里插入图片描述

通过系统调用获取进程标示符

关于系统调用:操作系统对外会表现为⼀个整体,但是会暴露⾃⼰的部分接⼝,供上层开发使⽤,这部分由操作系统提供的接⼝,叫做系统调⽤。系统调⽤在使⽤上,功能⽐较基础,对⽤⼾的要求相对也⽐较⾼,所以,有⼼的开发者可以对部分系统调⽤进⾏适度封装,从⽽形成库,有了库,就很有利于更上层⽤⼾或者开发者进⾏⼆次开发。
简单来说:操作系统是不相信任何人的,但是为了向上层提供服务,不得不暴露一些接口供用户使用,来访问操作系统。这些接口叫做系统调用。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{printf("pid: %d\n", getpid());printf("ppid: %d\n", getppid());return 0;
}

这里的getpid getppid就是系统调用,额…其实我觉得不如叫调用系统(的函数)。

通过系统调用创建进程-fork初识

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int gval = 100;int main()
{printf("父进程开始运行,pid: %d\n", getpid());pid_t id = fork();if(id < 0){perror("fork");return 1;}else if(id == 0){printf("我是一个子进程 !, 我的pid: %d, 我的父进程id: %d, gval: %d\n", getpid(), getppid(), gval);sleep(5);// childwhile(1){sleep(1);printf("子进程修改变量: %d->%d", gval, gval+10);gval+=10; // 修改printf("我是一个子进程 !, 我的pid: %d, 我的父进程id: %d\n", getpid(), getppid());}}else{//fatherwhile(1){sleep(1);printf("我是一个父进程 !, 我的pid: %d, 我的父进程id: %d, gval: %d\n", getpid(), getppid(), gval);}}printf("进程开始运行,pid: %d\n", getpid());
}

在这里插入图片描述
核心问题

  1. 为什么fork给父子进程返回值不相同?
  2. 为什么一个函数会返回两次?
  3. 为什么全局变量gval对于父子进程,值不相同?

问题1:因为父 : 子 = 1 :n,所以父进程要拿到子进程的id 。而对于子进程,返回0,让其知道自己是子进程即可。
问题2:因为fork函数创建了新的进程,而父子进程共享代码和数据。

fork() 系统调用的作用是创建一个与当前进程(父进程)几乎完全相同的新进程(子进程)。
子进程会复制父进程的地址空间(代码、数据、堆、栈等)、文件描述符、信号处理方式等。
从 fork() 调用之后开始,父子进程会各自独立执行后续的代码(共享同一份代码,但拥有独立的执行流)。

问题3:因为采用写时拷贝机制。

fork() 创建子进程时,系统采用写时拷贝机制:初始时,子进程共享父进程的地址空间(包括 gval),但这是只读的。当子进程尝试修改 gval 时,系统会为子进程复制一份 gval 的副本,此后父子进程的 gval 各自独立,修改互不干扰。这体现了进程独立性:每个进程有自己独立的地址空间,不受其他进程影响。


http://www.dtcms.com/a/511707.html

相关文章:

  • c#using Oracle.ManagedDataAccess.Client 批量保存数据
  • 人大金仓数据库kingbase8创建表示例
  • oracle包编译错误
  • 函数指针 指针函数 数组指针 指针数组 常量指针 指针常量
  • sqoop采集完成后导致hdfs数据与Oracle数据量不符的问题。怎么解决?
  • 洛阳有做网站开发的吗平台网站建设源码
  • 从零开始的C++学习生活 12:AVL树全面解析
  • Spring Boot 启动慢?启动过程深度解析与优化策略
  • telnet工具使用详解
  • YOLOv4:目标检测界的 “集大成者”
  • 从零开始的C++学习生活 11:二叉搜索树全面解析
  • 【QT常用技术讲解】控件随窗口自适应变化大小或者移动位置
  • Kafka面试精讲 Day 30:Kafka面试真题解析与答题技巧
  • 江苏建设准考证打印在哪个网站医疗网站 seo怎么做
  • 数据结构9:队列
  • 逆向分析星星充电APP:从签名生成到数据深度解析
  • Vue + WebApi 实现上传下载功能
  • 建设门户网站预算做旅游网站多少钱
  • 【Rust创作】Rust 错误处理:从 panic 到优雅控制
  • 常见激活函数的Lipschitz连续证明
  • 专做皮具的网站网站建设公司排行榜
  • 第三次面试:C++实习开发
  • 公司网站内容更新该怎么做wordpress显示目录
  • 边界扫描测试原理 2 -- 边界扫描测试设备的构成
  • 如何入侵网站后台晴天影视
  • Linux top 命令使用说明
  • 研发图文档管理的革新:从无序到智能协同
  • springboot点餐系统的设计与实现(代码+数据库+LW)
  • ArcoDesignVue Select组件分离问题
  • Python开发:接口场景设计