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

学习嵌入式第二十八天

文章目录

  • 进程和线程
    • 1.进程
      • 1.基本概念
      • 2.进程的创建
      • 3.进程相关的函数接口
      • 4.进程消亡
  • 习题

进程和线程

1.进程

1.基本概念

  • 程序:存放在外存中的一段数据的集合
  • 进程:是程序动态执行的过程,包括创建,调度和消亡

2.进程的创建

  1. 进程空间的分布

    • 每个进程运行起来后,操作系统开辟0 - 4G的虚拟内存空间
    • 进程空间:用户空间+内核空间(不允许用户访问)
    • 用户空间:文本段(文本区)+数据段(数据区)+系统数据段(堆区、栈区)
    • 文本段:存放代码和指令
    • 数据段:字符串常量、已初始化全局变量/静态变量、未初始化全局变量/静态变量
    • 数据区存放数据特点:
      • 未经初始化值为0值
      • 编译时开辟空间
      • 程序结束时回收空间
    • 系统数据段:堆区(malloc空间)、栈区(局部变量、函数运行)
    • 堆区存放数据特点:
      • malloc申请堆区空间
    • 栈区存放数据特点:
      • 未经初始化值为随机值
      • 执行到变量定义开辟内存空间
      • 超过变量作用域回收变量空间
  2. 虚拟地址和物理地址

    1. 虚拟地址
      • 所有能被用户看到的地址均为虚拟地址均为虚拟地址,表示用户可以寻址的范围
    2. 物理地址
      • 内存存放数据对应的实际硬件物理地址
    3. MMU
      • 实际地址和物理地址之间的映射由内存映射单元(MMU)完成
  3. 多进程存储

    • 存储方式

      • 多个进程空间在操作系统中存储时,空间是独立的(物理地址是独立的)

      • 多个进程在操作系统中共用同一个虚拟内存空间(虚拟地址是共享的)

  4. 多进程的调度

    1. 常见的进程调度算法
      1. 先来先执行,后来后执行
      2. 高优先级调度算法
      3. 时间片轮转调度算法
      4. 多级队列反馈调度算法
      5. 负载均衡调度算法
    2. 多进程调度的本质
      • 宏观并行,微观串行
  5. 进程相关命令

    1. top

      示例:top
      功能:根据CPU占用率和内存占用率查看当前所有进程的信息PID:唯一区分进程的ID号
      USER:创建者
      PR/NI:优先级
      VIRT/RES/SHR:资源占用
      S:状态
      %CPU:CPU占用率
      %MEM:内存占用率
      TIME+:运行时长
      COMMAND:进程命令
      
    2. ps -ef

      示例:ps -ef
      功能:查看该时刻所有进程信息UID:创建进程用户
      PID:进程的ID号
      TIME/CMDps -ef | grep 进程名
      查找与进程名对应的进程信息
      
    3. ps -aux

      示例:ps -aux功能:查看该时刻所有进程的信息USER:创建者
      PID:进程的ID号
      %CPU:CPU占用率
      %MEM:内存占用率 
      VSZ 
      RSS 
      TTY      
      STAT:进程的状态 
      START   
      TIME 
      COMMAND
      
    4. 后台执行进程任务

      示例:./a.out &
      功能:后台执行a.out进程
      
    5. jobs

      示例:jobs
      功能:查看终端下所有后台进程任务
      
    6. fg

      示例:fg 编号(通过jobs查看)
      功能:后台执行的任务被放到前台执行
      
    7. nice/renice

      示例:nice -n 优先级编号 进程名renice -n 优先级编号 进程PID
      功能:改变进程的优先级优先级范围:-20~20
      数字越小优先级越高
      
    8. kill/killall

      示例:kill -编号 进程PIDkillall -编号 进程名功能:杀死进程
      
  6. 进程的状态

    进程状态标识含义
    就绪态/运行态R进程位于CPU任务调度的队列中
    可唤醒等待态S等待某个资源的到来,资源到来后被唤醒加入调度队列,等待过程可被打断
    不可唤醒等待态D等待某个资源的到来,资源到来后被唤醒加入调度队列,等待过程不可被打断
    停止态T用户人为让进程任务暂停等待
    僵尸态Z进程代码运行结束,空间尚未回收
    结束态X进程代码运行结束,空间被回收

3.进程相关的函数接口

  1. fork

    原型:pid_t fork(void);
    功能:创建一个新的进程,新的进程称为子进程,调用fork的进程称为父进程
    参数:缺省
    返回值:父进程中返回子进程的PID子进程中返回0出错返回-1
    
    • 子进程拷贝父进程文本段、数据段、系统数据段
    • 父进程与子进程空间独立,同一份代码中的个变量和数据都会在父子进程中各有一份,父子进程修改自己空间的数据不会影响对方
    • 进程的PID不一样
    • fork的返回值不一样
    • PID > 0
  2. getpid和getppid

    原型:pid_t getpid(void);
    功能:获得调用函数进程的PID号原型:pid_t getppid(void);
    功能:获得调用函数父进程的PID号
    
  3. exit和_exit

    原型:void exit(int status);
    功能:结束进程任务并返回进程结束状态
    参数:status:进程结束的状态值原型:void _exit(int status);
    功能:结束进程任务并返回进程结束状态
    参数:status:进程结束的状态值
    返回值:
    
    • 在主程序中调用和return功能一致
    • return在函数内部将结束该函数
    • exit在函数中会结束该进程
    • exit会在结束前刷新缓存区
    • _exit不会刷新缓存区
  4. wait

    原型:pid_t wait(int *wstatus)
    功能:回收子进程空间
    参数:wstatus:存放子进程结束空间的首地址
    返回值:成功返回回收到的子进程的PID失败返回-1
    
    • wait具有阻塞等待功能,等到有子进程结束才会回收子进程继续向下执行

4.进程消亡

  1. 孤儿进程
    • 父进程先结束,子进程会变成孤儿进程,被init进程收养
  2. 僵尸进程
    • 每个进程结束必然会经历的阶段
    • 产生原因:子进程结束后,父进程没有回收子进程空间,导致进程执行结束,空间依然被占用的状态。
    • 避免产生僵尸进程
      • 父进程先结束,子进程会成为孤儿进程,孤儿进程被init进程收养,子进程再结束,init进程回收进程空间
      • 子进程结束,父进程回收子进程空间,

习题

编写一个程序,将当前系统中所有进程的PID、PPID、Name信息记录到record.txt文件中

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<math.h>
#include<time.h>
#include<sys/wait.h>int get_allnumdir(struct dirent *pp){char *pstr = NULL;pstr = pp->d_name;while(pstr != NULL && *pstr != '\0'){if(*pstr < '0' || *pstr > '9'){return -1;}pstr++;}return 1;
}
void get_information(FILE *fp1,char *name,char *pid,char *ppid){char buff[100] = {0};char *str = NULL;rewind(fp1);while(fgets(buff,sizeof(buff),fp1) != NULL){str = strtok(buff,"\t");if(0 == strcmp(str,"Name:")){str = strtok(NULL,"\n");strcpy(name,str);}else if(0 == strcmp(str,"Pid:")){str = strtok(NULL,"\n");strcpy(pid,str);}else if(0 == strcmp(str,"PPid:")){str = strtok(NULL,"\n");strcpy(ppid,str);}   }
}int main(void){FILE *fp = NULL;FILE *fp1 = NULL;DIR *dir = NULL;struct dirent *pp = NULL;char tmpbuff[4096] = {0};char ppid[10] = {0};char pid[10] = {0};char name[100] = {0};fp = fopen("record.txt","w");if(NULL == fp){perror("fail to fopen");return -1;}dir = opendir("/proc");if(NULL == dir){perror("fail to opendir");return -1;}while(1){tmpbuff[0] = '\0';memset(name, 0, sizeof(name));memset(pid, 0, sizeof(pid));memset(ppid, 0, sizeof(ppid));pp = readdir(dir);if(NULL == pp)break;if(get_allnumdir(pp) == 1){sprintf(tmpbuff,"/proc/%s/status",pp->d_name);fp1 = fopen(tmpbuff,"r");if(NULL == fp1){continue;}get_information(fp1,name,pid,ppid);fprintf(fp,"Name: %s\n",name);fprintf(fp,"PID: %s\n",pid);fprintf(fp,"PPID: %s\n",ppid);fclose(fp1);}}closedir(dir);fclose(fp);return 0;
}
http://www.dtcms.com/a/332106.html

相关文章:

  • 中山清华:基于大模型的具身智能系统综述
  • app-4 日志上传
  • 从0到1:C++ 语法之引用
  • qt项目中解决关闭弹窗后执行主界面的信号槽时闪退问题
  • 基于wireshark的USB 全速硬件抓包工具USB Sniffer Lite的使用
  • 多线程安全和性能测试
  • 珠海社保缴费记录如何打印
  • MyBatis Interceptor 深度解析与应用实践
  • CTFShow PWN入门---Kernel PWN 356-360 [持续更新]
  • 【嵌入式汇编基础】-ARM架构基础(五)
  • c/c++实现 TCP Socket网络通信
  • Docker存储卷备份策略于VPS服务器环境的实施标准与恢复测试
  • Linux 进程与内存布局详解
  • RecyclerView 拖拽与滑动操作
  • HQA-Attack: Toward High Quality Black-Box Hard-Label Adversarial Attack on Text
  • 多列集合---Map
  • 【无标题】设计文档
  • Cache的基本原理和缓存一致性
  • 基于大语言模型的爬虫数据清洗与结构化
  • 可信搜索中的多重签名
  • 系统日常巡检脚本
  • 将mysql数据库表结构导出成DBML格式
  • Qt---Qt函数库
  • ActionChains 鼠标操作笔记
  • # Vue 列表渲染详解
  • AI智能体|扣子(Coze)搭建【批量识别发票并录入飞书】Agent
  • FTP 服务详解:原理、配置与实践
  • 8月14日星期四今日早报简报微语报早读
  • [激光原理与应用-273]:理论 - 波动光学 - 光是电磁波,本身并没有颜色,可见光的颜色不过是人的主观感受
  • 时钟 中断 day54