Linux 进程概念

目录

冯诺依曼体系结构(了解)

周边知识

操作系统

如何管理

解释打印

★库函数

★系统调用

进程

概念

PCB

结构示意图

系统调用

监控脚本

[gitpid / gitppid](#gitpid / gitppid)

解释样例

chdir

/proc

解释样例

运行起来后删除磁盘中小体积的可执行程序

fork

概念

创建子进程的目的

工作原理

程序从上往下运行

★进程是独立运行的

样例解释

为什么会fork有两个返回值?

fork对于父子进程返回值不一样?

为什么id会有不同的值,确又是同一个地址?

总结


冯诺依曼体系结构(了解)

数据在硬件中的流通

周边知识

  • 计算机里几乎所有的设备都有存储数据的能力
  • CPU的数据处理能力很强;内存(掉电易失性存储单元);外设,硬盘(ssd固态硬盘),磁盘(永久的存储介质,机械结构)
  • 设备交互的本质是数据的拷贝;存储的效率直接决定了拷贝的效率决定了设备和设备间通信的效率
  • 数据层面上,当代CPU一般不直接和外设交互,优先和内存交互
  • 内存可以理解为一个硬件级别的大的缓存
  • 冯诺依曼体系结构的本质是:用较少的钱,做出效率不错的计算机(高性价比)
  • 程序运行之必须先加载到内存,使CPU读取其可执行程序的内存和数据(计算机层面都为二进制)

操作系统

  • 操作系统是开机第一个加载的软件
  • 是一款软硬件资源管理的软件(对下手段),为了给用户提供高效,稳定,安全的运行环境
  • 底层硬件采取冯诺依曼的体系结构
  • 除了CPU和内存外都需要驱动程序
  • ★操作系统内部有大量的数据对象和数据结构
  • 操作系统之上不是用户而是系统调用

如何管理

  • 先描述 (硬件的重要属性集合)被管理的对象 ;再通过数据结构将它们组织起来

解释打印

  • 往显示器打印的本质是往底层的硬件打印,操作系统不允许用户直接访问操作系统 ,那么更不会允许用户直接访问驱动程序或者对应的硬件 ,几乎用户的所有行为都必须贯彻操作系统,所以会通过printf这个库函数与操作系统的输出功能进行交互,然后由操作系统帮助向硬件打印
  • 所有语言中的大部分功能都和系统调用有关,所以printf必定封装了系统调用
  • 系统调用是上层访问下层的唯一通道

★库函数

  • 通常调用 系统调用 (因为底层封装了系统调用)来实现更高级别的功能
  • 库函数是应用程序调用的函数,通常是由编程语言的标准库或第三方库提供的

★系统调用

  • 是最底层的,是操作系统内核提供的接口,是程序与操作系统内核直接交互的接口
  • 允许用户的程序请求操作系统执行一些特权操作
  • 系统调用通常通过封装在标准库中的函数接口来访问

进程

概念

  • 可执行程序被加载到了内存,而操作系统为了更好管理进程,通过创建对应的PCB(进程 = 可执行程序 + 内核数据结构);管理的本质是管理PCB,数据(程序加载到内存的代码段和数据段...(二进制代码和数据))

PCB

  • 进程控制块(Process Control Block);进程的结构体对象
  • 包含多种属性:id,代码地址,数据地址,进程状态,优先级,链接字段...
  • 操作系统通过进程控制块来管理进程
  • task_struct是Linux内核中具体实现的PCB
  • PCB 是操作系统管理进程的核心数据结构 ,PCB 完全由操作系统内核创建、管理和销毁。因此,PCB 是操作系统内核的一部分
  • 描述进程的PCB在排队,而不是程序在排队

结构示意图

  • task_struct 是用于描述每个进程的通用数据结构,所有进程(无论类型如何)都使用这个结构体
  • 纠正:如果在task_struct里实现链接,这也是合理的,链接又很多种方式
  • 一个进程的PCB可以在多个链表里,这是操作系统内核管理和调度进程的重要机制之一
  • 可以通过cur(list)宏 来得到task_struct的地址

系统调用

监控脚本

  • while :; do ps axj | head -1 && ps axj | grep mybin | grep -v "grep"; sleep 1; echo ""; done
  • 用于动态观察
  • grep命令启动的时候也包含mybin

gitpid / gitppid

  • pid:进程标识符,操作系统用来唯一标识每个进程的一个数字
  • 通过系统调用拿到pid或者ppid
  • kill -9 pid :kill的-9选项可以通过pid杀进程

解释样例

cpp 复制代码
#include <stdio.h>    
#include <unistd.h>    
    
int main()    
{    
    printf("这个进程的pid:%d, ppid:%d\n", getpid(), getppid());        
    while(1)    
    {    
        sleep(1);                                       
    }    
    return 0;    
}
  • 发现32001是一个叫bash的进程
  • bash是shell(命令行解释器)的一种
  • 运行的ps axj命令的父进程是bash
  • 结论:通过命令行解释器(bash)启动的进程的父进程都是bash(bash在登陆后就不变了)
  • 启动进程意味着 进程一般是由其父进程创建

chdir

/proc

  • 是一个虚拟文件系统 ,用于提供关于系统和进程的信息,每个正在运行的进程在 /proc 目录下都有一个对应的子目录,该子目录的名称就是该进程的进程ID
  • 是一个动态的目录结构,存放的是所有存在的进程,目录名就是进程的pid
  • ★exe指向了该进程当前正在执行的可执行文件的路径
  • cwdcurrent work directory 当前工作目录
解释样例
cpp 复制代码
chdir("/home/wzf/Linux");//修改cwd路径
FILE* fp = fopen("test.txt", "w");
  • 会在/home/wzf/Linux的工作目录下创建test.txt文件
  • 这里的fopen也可以写成./text.txt,就是相对于cwd去比照
  • 结论:默认情况下,进程启动时所处的路径就是当前路径
  • 结论:每一个进程都要有自己的工作目录
运行起来后删除磁盘中小体积的可执行程序
  • 当一个可执行程序被加载到内存中执行时,文件的内容(机器指令,数据段,代码段,堆栈段)已经被操作系统读取并加载到内存中。此时,即使删除了文件系统中的可执行文件,已经在运行的进程不会受到影响
  • 如果这个可执行程序不是一次全加载到内存上的,进程当然受到影响

fork

概念

  • Linux 系统中,所有进程都是通过 fork() 机制派生出来的

创建子进程的目的

  • 让子进程协助父进程完成一些单进程解决不了的任务
  • 多进程多在服务端(简单来说需要同时处理多个客户端的请求),客户端较少

工作原理

  • 以父进程为模版,复制父进程的虚拟地址空间、文件描述符、寄存器状态等。子进程与父进程几乎完全相同,先全部拷贝到子进程再修改部分信息

程序从上往下运行

  • 进程运行时,CPU里有个(指令指针)eip寄存器(x86架构)/pc指针(arm架构),会保存当前正在执行的指令的地址;当处理器执行一条指令时,eip会指向下一条指令的地址;eip寄存器的值 也会被子进程继承

★进程是独立运行的

  • ★每个进程有自己独立的上下文 ,包含寄存器状态、内存映射;当进程在 CPU 上运行时,操作系统会加载该进程的上下文到 CPU 中,父进程和子进程虽然共享相同的 EIP 值,但在实际执行时,它们是独立运行的,因为它们拥有各自的进程上下文

样例解释

cpp 复制代码
#include <stdio.h>    
#include <sys/types.h>    
#include <unistd.h>    
    
int main()    
{    
    pid_t id = fork();    
    if(id < 0)    
        return -1;    
    else if(id == 0)    
    {    
        while(1)    
        {    
            printf("子进程的pid:%d, ppid:%d, &id=%p\n", getpid(), getppid(), &id);    
            sleep(1);    
        }    
    }    
    else    
    {    
        while(1)                                                                                         
        {    
            printf("父进程的pid:%d, ppid:%d, &id=%p\n", getpid(), getppid(), &id);    
            sleep(1);    
        }    
    }    
}
为什么会fork有两个返回值?
  • 因为子进程在fork的return之前就已经创建好了(eip也被拷贝了),所以return语句子进程也要执行,那么就会有两个返回值
fork对于父子进程返回值不一样?
  • 返回子进程的 PID,这允许父进程知道子进程已经成功创建,并且可以使用这个 PID 来管理子进程,比如等待它终止或者发送信号
  • 在子进程中,fork 返回0 ;这是为了让子进程识别自己,并执行与父进程不同的操作
为什么id会有不同的值,确又是同一个地址?
  • 虚拟地址空间详解

总结

  1. 了解冯诺依曼结构及周边知识
  2. 操作系统的了解
  3. 进程和内核数据结构PCB
  4. cwd,pwd就是打印出cwd
  5. ★fork的理解,样例的解释
相关推荐
well_fly34 分钟前
Ubuntu特殊目录
linux·ubuntu
落落落sss44 分钟前
es实现自动补全
大数据·服务器·elasticsearch·搜索引擎·全文检索
大熊程序猿1 小时前
ubuntu 安装k3s
linux·运维·ubuntu
luoqice1 小时前
CentOS 自启动某个应用
linux·运维·服务器
泠山1 小时前
ubuntu增加swap交换空间
linux·运维·ubuntu
JavaOpsPro2 小时前
jenkins部署手册
运维·jenkins·离线部署
hero_th2 小时前
[Ubuntu] 文件/目录权限更改
linux·ubuntu
wclass-zhengge2 小时前
SpringBoot篇(运维实用篇 - 临时属性)
运维·spring boot·后端
速盾cdn2 小时前
速盾:什么是高防CDN?高防CDN的用处有哪些?
运维·服务器·网络·web安全