Linux系统进程

news2025/4/5 18:32:12

Linux系统进程

  • 程序开始
  • 编译链接的引导代码
    操作系统下的应用程序在main执行前也需要先执行段引导代码才能去执行main,但写应用程序时不用考虑引导代码的问题,编译连接时(准确说是链接时)由链接器将编译器中事先准备好的引导代码给链接进去,和应用程序一起构成最终的可执行程序。
  • 运行时的加载器
    加载器是操作系统中的程序,当执行一个程序时(e.g., ./a.out,代码中用exec族函数来运行)加载器负责将这个程序加载到内存中去执行这个程序。
  • 程序结束
  • 正常终止:return、exit、_exit
  • 非正常终止:自已或他人发信号终止进程(e.g., ctrl + c )
  • atexit
    atexit注册多个进程终止函数时,先注册的后执行。(先进后出,和栈一样)
    return和exit效果一样,都会执行进程终止函数;_exit不会执行进程终止函数,即刻终止进程。
#include <stdio.h>
#include <stdlib.h>

//以下func1,func2,func3都是进程终止函数
void term_func1(void){
        puts("term func1");
}
void term_func2(void){
        puts("term func2");
}
void term_func3(void){
        puts("term func3");
}

int main(int argc , char *args[]){
	primtf("hello world");

    atexit(term_func1);
    atexit(term_func2);
    atexit(term_func3);

    exit(0);
}
  • 进程环境
  • 环境变量,可以认为是操作系统的全局变量。
  • export
    查看环境变量
  • 环境变量表
    每一个进程中都有一份所有环境变量构成的一个表格,也就是说当前进程中可以直接使用这些环境变量。进程环境表其实是一个字符串数组,用environ变量指向它。
extern char **environ;
int i=0;
while(*(environ+i)!=NULL){
     printf("%s\n",*(environ+i));
     i++;
}
  • 进程运行的虚拟地址空间

操作系统中每个进程在独立地址空间中运行,每个进程的逻辑地址空间均为4GB(32位系统)。
进程隔离,提供多进程同时运行。

  • 进程

进程是一个动态过程而不是像文件一样的静态实物。进程就是程序的一次运行过程,一个静态的可执行程序a.out的一次运行过程(.
/a.out去运行到结束)就是一个进程。

  • 进程控制块PCB(process control block)
    内核中专门用来管理一个进程的数据结构。
  • 进程ID(PID, process ID)
    用数字标识不同的进程,用getpid获取。
  • 多进程调度
    操作系统同时运行多个进程,其实宏观上是并行,微观上是串行。实际上,现代操作系统最小的调度单元是线程而不是进程。
    getpid
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 int main()
 {
    printf("pid: %d\n", getpid());
    printf("ppid: %d\n", getppid());
    
    return 0;
  }
  • 父进程
  • fork
    子进程继承父进程中打开的文件。父进程先open打开一个文件得到fd,然后再fork创建子进程。之后在父子进程中各自write向fd中写入内容,结果是接续写。实际上本质原因是父子进程之间的fd对应的文件指针是彼此关联的。
    父进程open打开1.txt然后写入,子进程打开1.txt然后写入,结果是分别写。原因是父子进程分离后才各自打开的1.txt,这时候这两个进程的PCB已经独立了,文件表也独立了,因此2次读写是完全独立的。
  • 僵尸进程
    进程结束时,操作系统会释放此进程占用的资源,但并操作系统不能回收进程本身占用的内存(进程结构体),需要父进程回收。在子进程结束后,父进程还没有回收子进程本身占用的内存,这时的子进程称为僵尸进程。父进程通过调用wait或waitpid来回收子进程。
  • 孤儿进程
    父进程先于子进程结束,此时操作系统会负责回收。
  • pid_t wait(int *wstatus);
    子进程结束时,系统向其父进程发送SIGCHILD信号,父进程调用wait函数后阻塞,父进程被SIGCHILD信号唤醒然后去回收僵尸子进程;若父进程没有任何子进程则wait返回错误。wait主要是用来回收子进程资源,回收同时还可以得知被回收子进程的pid和退出状态。
    status: status用来返回子进程结束时的状态,父进程通过wait得到status后就可以知道子进程的一些结束状态信息。
    pidt: 返回值是本次wait回收的子进程的PID。当前进程有可能有多个子进程,wait函数阻塞直到其中一个子进程结束wait就会返回,wait的
    返回值就可以用来判断到底是哪一个子进程本次被回收了。
    WIFEXITED、WEXITSTATUS等宏用来判断退出状态。
  • exec族函数

fork子进程是为了执行新程序 ,可以直接在子进程的if中写入新程序的代码。这样可以,但是不够灵活,因为我们只能把子进程程序的源代码贴过来执行,但使用exec族可以运行新的可执行程序。

  • int execl(const char *pathname, const char *arg, ... /* (char *) NULL */);
    可以用来执行一个程序,区别是传参的格式不同。execl是把参数列表(本质上是多个字符串,必须以NULL结尾)依次排列而成。(l其实
    就是list的缩写)
  • int execv(const char *pathname, char *const argv[]);
    execv是把参数列表事先放入一个字符串数组中,再把这个字符串数组传给execv函数。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t pid;
    pid = fork();
    if (pid == -1) {
       perror("fork失败");
       exit(-1);
    } else if (pid == 0) {
       // 子进程
       // 使用execl执行/bin/ls -l命令
       if (execl("/bin/ls", "ls", "-l", NULL) == -1) {
          perror("execl失败");
          exit(-1);
       }
    } else {
       // 父进程
       // 可以在这里做其他事情,或者等待子进程结束
       // 这里简单地等待子进程结束
       wait(NULL);
       printf("子进程执行完毕。\n");
    }
    exit(0);
}
//execv_test.c 
#include<unistd.h>
 
int main()
{
    char * argv[ ]={"ls","-al","/usr",(char*)0};
    execv("/bin/ls",argv);
    
    return 0;
} 
  • 进程状态

进程的5种状态:

  • 就绪态 这个进程当前所有运行条件就绪,只要得到了CPU时间就能直接运行。
  • 运行态 就绪态时得到了CPU就进入运行态开始运行。
  • 僵尸态
  • 等待态(浅度睡眠&深度睡眠)进程在等待某种条件,条件成熟后可进入就绪态。等待态下就算给CPU调度进程也无法执行。
  • 停止态
  • system函数

system函数= fork+exec,属于原子操作,一旦开始就会不被打断的执行完。原子操作的好处就是不会被人打断(不会引来竞争状态),坏处是自己单独连续占用CPU时间太长影响系统整体实时性,因此应该尽量避免不必要的原子操作,就算不得不原子操作也应该尽量原子操作的时间缩短。

  • 进程关系
  1. 无关系 两个进程独立的,无法相互访问。
  2. 父子进程关系 继承
  3. 进程组(group)多个进程构成一个进程组,每个进程组都有唯一的进程组ID(整数,也可以存放在pid_t类型中)。
  4. 会话(session)多个进程组构成一个会话。
  • ps

process status
ps -ajx 偏向显示各种有关的ID号
ps -aux 偏向显示进程各种占用资源

  • kill

kill -信号编号 进程ID,向一个进程发送一个信号
kill -9 xxx,将向xxx这个进程发送9号信号,也就是要结束进程

  • 守护进程

守护进程(daemon),进程名后面加字母d标识,是一类在后台运行的特殊进程,与控制台脱离。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。
服务器(Server),服务器程序就是一个一直在运行的程序,可以给我们提供某种服务(比如,nfs服务器给我们提供nfs通信方式),当我们程序需要这种服务时我们可以调用服务器程序(和服务器程序通信以得到服务器程序的帮助)来进程这种服务操作。服务器程序一般都实现为守护进程。

  • syslogd
    守护进程无法输入输出,只能用syslogd调试信息。操作系统中有一个守护进程syslogd(开机运行,关机时才结束),这个守护进
    程syslogd负责进行日志文件的写入和维护。syslogd是独立于任意一个进程而运行的。
    • openlog
      当前进程和syslogd进程是没有任何关系的,但是当前进程可以通过调用openlog打开一个和syslogd相连接的通道,然后通过syslog向syslogd发消息,然后由syslogd来将其写入到日志文件系统中。
    • syslogd
    • closelog
  • cron
    操作系统时间管理,定时执行程序。
  • 将一个进程实现成守护进程
    create daemon函数要素
    (1)子进程等待父进程退出
    (2)子进程使用setsid创建新的会话期,脱离控制台
    (3)调用chdir将当前工作目录设置为/
    (4)umask设置为0以取消任何文件权限屏蔽
    (5)关闭所有文件描述符
    (6)将0、1、2定位到/dev/null
void create_daemon() {
    pid_t pid;
    pid = fork();

    if (pid == -1) {
        perror("fork error\n");
        exit(-1);
    } else if (pid) {
        exit(0);
    }

    if (-1 == setsid()) {
        perror("setsid error\n");
        exit(-1);
    }

    chdir("/");
    umask(0);
    int cnt = sysconf(_SC_OPEN_MAX);
    int i;
    for (i = 0; i < cnt ; ++i) {
        close(i);
    }
    open("/dev/null", RDWR);
    open("/dev/null", RDWR);
    open("/dev/null", RDWR);
}
  • 让守护进程只执行一次
  • 进程间通信(IPC, Inter-Process Communication)
    复杂、大型的程序,因为设计的需要就必须被设计成多进程程序,常见的如GUI、服务器。
    (1)管道(无名管道)和有名管道
    (2)SystemVIPC:信号量、消息队列、共享内存
    (3)Socket域套接字
    (4)信号
    • 管道(无名管道)
      (1)管道通信的原理:内核维护的一块内存,有读端和写端(管道是单向通信的)
      (2)管道通信的方法:父进程创建管理后fork子进程,子进程集成父进程的管道fd
      (3)管道通信的限制:只能在父子进程间通信、半双工
      (4)管道通信的函数:pipe、write、read、close
    • 有名管道(fifo)
      (1)有名管道的原理:实质也是内核维护的一块内存,表现形式为一个有名字的文件
      (2)有名管道的使用方法:固定一个文件名,2个进程分别使用mkfifo创建fifo文件,然后分别open打开获取到fd,然后一个读一个写
      (3)管道通信限制:半双工(注意不限父子进程,任意2个进程都可)
      (4)管道通信的函数:mkfifo、open、write、read、close
  • SystemVIPC介绍
    SystemVIPc的基本特点:
    (1)系统通过一些专用API来提供SystemVIPC功能
    (2)分为:信号量、消息队列、共享内存
    (3)其实质也是内核提供的公共内存
    • 消息队列
      (1)本质上是一个队列,队列可以理解为(内核维护的一个)FIFO
      (2)工作时A和B2个进程进行通信,A向队列中放入消息,B从队列中读出消息。
    • 信号量
      (1)实质就是个计数器
      (2)通过计数值来提供互斥和同步
    • 共享内存
      (1)大片内存直接映射
      (2)类似于LCD显示时的显存用法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2328746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Cursor】切换主题

右键顶部&#xff0c;把菜单栏勾上 首选项-主题-颜色主题 选择和喜欢的颜色主题即可&#xff0c;一般是“现代深色”

spring druid项目中监控sql执行情况

场景 在 Spring Boot 结合 MyBatis 的服务中&#xff0c;实现 SQL 执行覆盖情况的监控&#xff0c;可以基于Druid提供的内置的 SQL 监控统计功能。 开启监控 在 application.yml 中启用 Druid 的 stat 和 wall 过滤器&#xff0c;并配置监控页面的访问权限 …

Obsidian按下三个横线不能出现文档属性

解决方案: 需要在标题下方的一行, 按下 键盘数字0后面那个横线(英文横线), 然后回车就可以了 然后点击横线即可

pyqt SQL Server 数据库查询-优化2

1、增加导出数据功能 2、增加删除表里数据功能 import sys import pyodbc from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QLineEdit, QPushButton, \QTableWidget, QTableWidgetItem, QLabel, QMessageBox from PyQt6.QtGui i…

Hyperlane:高性能 Rust HTTP 服务器框架评测

Hyperlane&#xff1a;高性能 Rust HTTP 服务器框架评测 在当今快速发展的互联网时代&#xff0c;选择一个高效、可靠的 HTTP 服务器框架对于开发者来说至关重要。最近&#xff0c;我在评估各种服务器框架性能时&#xff0c;发现了一个名为 Hyperlane 的 Rust HTTP 服务器库&a…

Laravel 中使用 JWT 作用户登录,身份认证

什么是JWT&#xff1a; JWT 全名 JSON Web Token&#xff0c;是一种开放标准 (RFC 7519)。 用于在网络应用环境间安全地传输信息作为 JSON 对象。 它是一种轻量级的认证和授权机制&#xff0c;特别适合分布式系统的身份验证。 核心特点 紧凑格式&#xff1a;体积小&#x…

VBA中类的解读及应用第二十二讲:利用类判断任意单元格的类型-5

《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。 类&#xff0c;是非常抽象的&#xff0c;更具研究的价值。随着我们学习、应用VBA的深入&#xff0…

STM32F103_LL库+寄存器学习笔记13 - 梳理外设CAN与如何发送CAN报文(串行发送)

导言 CAN总线因其高速稳定的数据传输与卓越抗干扰性能&#xff0c;在汽车、机器人及工业自动化中被广泛应用。它采用分布式网络结构&#xff0c;实现多节点间实时通信&#xff0c;确保各控制模块精准协同。在汽车领域&#xff0c;CAN总线连接发动机、制动、车身系统&#xff0c…

Linux系统调用编程

文章目录 一、进程和线程二、Linux的虚拟内存管理和stm32的真实物理内存**Linux虚拟内存管理**STM32物理内存映射2. 主要区别 三、Linux系统调用函数 fork()、wait()、exec()1. fork()&#xff1a;创建子进程2. wait()&#xff1a;等待子进程状态改变3. exec()&#xff1a;替换…

游戏引擎学习第203天

回顾当前情况 在这里我将直播完成整个游戏的制作。我们现在面临一些技术上的困难&#xff0c;确实如此。我的笔记本电脑的电源接口坏了&#xff0c;所以我不得不准备了这台备用笔记本&#xff0c;希望它能够正常工作。我所以希望一切都还好&#xff0c;尽管我不完全确定是否一…

深度学习数据集划分比例多少合适

在机器学习和深度学习中&#xff0c;测试集的划分比例需要根据数据量、任务类型和领域需求灵活调整。 1. 常规划分比例 通用场景 训练集 : 验证集 : 测试集 60% : 20% : 20% 适用于大多数中等规模数据集&#xff08;如数万到数十万样本&#xff09;&#xff0c;平衡了训练数…

CExercise_1_5 水仙花数

题目&#xff1a; 经典循环案例&#xff1a;请求出所有的水仙花数&#xff0c;并统计总共有几个。 所谓的水仙花数是指一个三位数&#xff0c;其各位数字的立方和等于该数本身。 举例&#xff1a;153就是一个水仙花数&#xff0c;153 1 * 1 * 1 5 * 5 * 5 3 * 3 * 3 1 125…

哈密尔顿路径(Hamiltonian Path)及相关算法题目

哈密尔顿路径要求访问图中每个顶点恰好一次&#xff0c;通常用于解决旅行商问题&#xff08;TSP&#xff09;或状态压缩DP问题。 哈密尔顿路径&#xff08;Hamiltonian Path&#xff09;是指在一个图中经过每个顶点恰好一次的路径。如果这条路径的起点和终点相同&#xff08;即…

MINIQMT学习课程Day10

开始获取股票数据课程的学习&#xff1a; 获取qmt账号的持仓情况后&#xff0c;我们进入下一步&#xff0c;如何获得当前账号的委托状况 还是之前的步骤&#xff0c;打开qmt&#xff0c;选择独立交易&#xff0c; 之后使用pycharm&#xff0c;编写py文件 导入包&#xff1a…

JAVA实战开源项目:智慧图书管理系统(Vue+SpringBoot) 附源码

本文项目编号 T 152 &#xff0c;文末自助获取源码 \color{red}{T152&#xff0c;文末自助获取源码} T152&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

Linux 系统管理综合实训 —— 基于 NAT 模式的多 IP 配置、Nginx 服务部署及存储管理

1. 虚拟机网络配置&#xff1a;NAT模式与多IP地址设置 将你的虚拟机的网卡模式设置为nat模式&#xff0c;给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 设置静态IP [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 192.168.2.100/2…

如何在windows 环境、且没有显卡的情况下用python跑通从ModelScope下载的大模型的调用

文章目录 背景介绍源代码&#xff1a;安装调试过程1.设置第三方镜像源2.预先安装&#xff1a;3.在python中创建代码&#xff1a;4.最终修改程序,将device_map从“cuda”改成“auto”&#xff0c;大模型调用1.5B&#xff08;1___5B)的5.最终跑出结果解释&#xff1a;示例&#x…

黑马点评redis改 part 1

本篇将主要阐述短信登录的相关知识&#xff0c;感谢黑马程序员开源&#xff0c;感谢提供初始源文件&#xff08;给到的是实战第7集开始的代码&#xff09;【Redis实战篇】黑马点评学习笔记&#xff08;16万字超详细、Redis实战项目学习必看、欢迎点赞⭐收藏&#xff09;-CSDN博…