【Linux】进程控制与进程调度

news2025/1/16 14:02:07

Linux进程介绍 

进程的基本概念

Linux是多用户、多任务的操作系统。在这样的环境中,各种计算机资源的分配和管理都是以进程为单位进行的。

Linux操作系统包括三种不同类型的进程:

1)交互进程:一种由Shell启动的进程。交互进程既可在前台进行,也可在后台运行。前者称为前台进程,后者为后台进程。前台进程可与用户通过Shell进行交互。

2)批处理进程:与终端没有联系,是系列进程,即多个进程按照指定的方式执行。

3)守护进程:运行在后台的一种特殊进程,在系统启动时启动,并在后台运行。守护进程本身不在屏幕上显示任何信息,但会在后台悄悄地为用户服务,例如运行的网络服务程序。

描述进程的数据结构

在操作系统中,进程是指运行中的程序实体。此外还包括这个运行的程序所占据的所有系统资源,如CPU、设备、内存、网络资源等。Linux中,可以用ps命令得到当前系统中进程的列表。

在Linux中每个进程在被创建时都会分配一个结构体 task_struct,即进程控制块PCB。

task_struct结构体虽然庞大而复杂,但其中信息可以归为以下几类:

1)标识信息:唯一标识一个进程

2)状态信息

        1.运行:进程处于运行状态或者准备运行状态。

        2.等待:进程在等待一个事件或资源。又分为两类,可中段(可被信号中断),不可中断(由于硬件原因而等待)

        3.停止:进程处于停止状态。

        4.跟踪:进程正在被跟踪。

        5.僵死:进程已终止。

        6.死亡:表示进程处于退出过程,它所占的所有资源都会被回收。

3)调度信息:调度进程所需要的信息,如:进程类型、优先级、允许进程执行的时间片。

Linux进程调度介绍

进程调度就是进程程序按照一定的策略,动态地把CPU分配给处于就绪队列中的某个进程。

Linux操作系统中存在两类进程,即普通进程和实时进程。任何实时进程的优先级都高于普通进程的优先级。

普通进程用nice值得表示优先级,取值范围为[-20,19],默认为0。越低的nice值代表越高的优先级,越高优先级的普通进程有越高的执行时间。

实时优先级是可配置的,默认范围是[0,99]。与nice值相反,越高的实时优先级数值代表越高的优先级。 

进程控制函数介绍

在Linux操作系统中,fork()函数用来创建一个新的进程,exec函数用来启动另外的程序以取代当前运行的进程。

1.创建进程

在Linux中,创建进程的常见方法是使用fork函数从已经存在的进程(父进程)中创建一个新进程(子进程)。子进程是父进程的副本,子进程和父进程使用相同的代码包;子进程复制父进程的数据与堆栈空间,并继承父进程的用户代码等。由于子进程完全复制了父进程 ,因此父子进程会运行同一个程序。

int fork();

返回值意义如下:

大于等于0:正确返回

        1)等于0,当前是子进程,从子进程返回进程ID值

        2)大于0,表示当前进程是父进程,从父进程返回进程ID值

小   于    0 :错误返回,表示进程创建失败;原因:进程数达到上限/内存不足

子进程虽然继承了父类的一切数据,当子进程一旦开始运行,就会和父进程分开。子进程拥有自己的ID、资源、计时器等,与父进程之间不再共享数据。

2.管理进程标识符

int getpid();           //取得当前进程的标识符
int getppid();          //取得当前进程的父进程ID
int getpgrp();          //取得当前进程的组标识符
int getpgid(int pid);   //将当前进程的组标识符改为当前进程的ID

3.加载新的进程映像

execlp函数使用 - erictanghu - 博客园 (cnblogs.com)

execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……最后一个参数必须用空指针(NULL)作结束。如果用常数0来表示一个空指针,则必须将它强制转换为一个字符指针,否则将它解释为整形参数,如果一个整形数的长度与char * 的长度不同,那么exec函数的实际参数就将出错。如果函数调用成功,进程自己的执行代码就会变成加载程序的代码,execlp()后边的代码也就不会执行了.

4.wait函数

wait()和waitpid()的一些理解_wait(null)与wait(0)区别-CSDN博客

wait()系统调用挂起调用的执行进程,直到其子进程之一终止。

5.终止进程执行

void exit(int status);

一个进程自我终止后,将释放所占资源并通知父进程可以删除它,此时它处于僵死状态。参数status是调用进程终止执行时传递给其父进程的值。

实践

1.#include <unistd.h>
2.#include <sys/types.h>
3.#include <errno.h>
4.#include <sys/wait.h>
5.#include <stdlib.h>
6.#include<stdio.h>
7.int main()
8.{
9.   pid_t childpid; //放子进程的id
10.   int retval;     //设置的子进程的返回值
11.   int status;     //子进程向父进程提供的退出状态
12.
13.   childpid=fork();//创建新进程
14.   if(childpid>=0) //创建成功
15.   {
16.      if (childpid==0) //说明当前进程就是子进程
17.      {
18.        printf("CHILD: I am the child process! \n");
19.        printf("CHILD: Here's my PID: %d\n", getpid());//getpid获得当前进程id
20.        printf("CHILD: My parent's PID is: % d\n", getppid());//grtppid获得父进程id
21.        printf("CHILD: The value of fork return is: % d\n", childpid);//fork的返回值
22.        printf("CHILD: Sleep for 1 second...\n");
23.        sleep(1);//让当前进程睡眠1秒
24.
25.        printf("CHILD: Enter an exit value (0~255): ");
26.        scanf("%d",&retval);//设置子进程返回值
27.        printf("CHILD: Goodbye! \n"); 
28.        exit(retval); //子进程退出,退出值为刚刚设置的
29.      }
30.      else  //当前进程为父进程
31.      {
32.        printf("PARENT: I am the parent process! \n");
33.        printf("PARENT: Here's my PID: %d\n", getpid());//当前进程id
34.        printf("PARENT: The value of my child's PID is: %d\n", childpid);//子进程id
35.
36.        printf("PARENT: I will now wait for my child to exit.\n");
37.        wait(&status); //等待子进程运行结束,并保存其状态
38.        printf("PARENT: Child's exit code is: %d\n", WEXITSTATUS(status));//输出子进程的返回值
39.
40.        printf("PARENT: Goodbye! \n"); 
41.        exit(0); //父进程退出
42.      }
43.  }
44.  else //创建失败
45.  {
46.     perror("fork error!"); /*display error messsage*/
47.     exit(0);
48.   }
49.}
1.#include<stdio.h>
2.#include<unistd.h>
3.#include<sys/types.h>
4.#include<sys/wait.h>
5.int main()
6.{
7.   pid_t  pid;
8. pid = fork();//创建新进程
9. if (pid < 0) { //进程创建失败
10.  fprintf(stderr, "Fork Failed");//输出内容到文件
11.  return 1;
12. }
13. else if (pid == 0) { //当前是子进程
14.                execlp("/bin/ls","ls",NULL);
15.  //execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束。如果用常数0来表示一个空指针,则必须将它强制转换为一个字符指针,否则将它解释为整形参数,如果一个整形数的长度与char * 的长度不同,那么exec函数的实际参数就将出错。如果函数调用成功,进程自己的执行代码就会变成加载程序的代码,execlp()后边的代码也就不会执行了.
16. }
17. else { //父进程
18.  wait (NULL);
19.  //wait()系统调用挂起调用的执行进程,直到其子进程之一终止。
20.  printf ("Child Complete");
21. }
22.        return 0;
23.}

模拟调度算法 

1.#include "stdio.h" 
2.#include <stdlib.h> 
3.#define getpch(type) (type*)malloc(sizeof(type)) 
4.
5.//模拟进程调度算法
6.struct pcb { /* 定义进程控制块PCB */ 
7.  char name[10]; //进程名
8.  char state;    //进程状态:"W"-就绪态,"R"-运行态,F完成
9.  int nice;      //进程优先级
10.  int ntime;     //需要运行时间
11.  int rtime;     //已经运行的时间
12.  struct pcb* link;  
13.}*ready=NULL,*p; 
14.typedef struct pcb PCB; 
15.
16.char sort() /* 建立对进程进行优先级排列函数,优先数大者优先*/ 
17.{ //
18.  PCB *first, *second; 
19.  int insert=0; 
20.  if((ready==NULL)||((p->nice)>(ready->nice)))/*优先级最大者,插入队首*/ 
21.  { 
22.    p->link=ready; 
23.    ready=p; 
24.  } 
25.  else /* 进程比较优先级,插入适当的位置中*/ 
26.  { 
27.    first=ready; 
28.    second=first->link; 
29.    while(second!=NULL) 
30.    { 
31.      if((p->nice)>(second->nice)) /*若插入进程比当前进程优先数大,*/ 
32.      { /*插入到当前进程前面*/ 
33.        p->link=second; 
34.        first->link=p; 
35.        second=NULL; 
36.        insert=1; 
37.      } 
38.      else /* 插入进程优先数最低,则插入到队尾*/ 
39.      { 
40.        first=first->link; 
41.        second=second->link; 
42.      } 
43.    } 
44.    if(insert==0) first->link=p; 
45.  } 
46.} 
47.
48.char input() /* 建立进程控制块函数*/ 
49.{ //输入
50.  int i,num; 
51.  printf("\n 请输入被调度的进程数目:"); 
52.  scanf("%d",&num); 
53.  for(i=0;i<num;i++) 
54.  { 
55.    printf("\n 进程号No.%d:",i); 
56.    p=getpch(PCB); 
57.    printf("\n 输入进程名:"); 
58.    scanf("%s",p->name); 
59.    printf(" 输入进程优先数:"); 
60.    scanf("%d",&p->nice); 
61.    printf(" 输入进程运行时间:"); 
62.    scanf("%d",&p->ntime); 
63.    printf("\n"); 
64.    p->rtime=0;
65.    p->state='W'; 
66.    p->link=NULL; 
67.    sort(); /* 调用sort函数*/ 
68.  } 
69.} 
70.
71.int space() //统计链表中结点个数
72.{ 
73.  int l=0; PCB* pr=ready; 
74.  while(pr!=NULL) 
75.  { 
76.    l++; 
77.    pr=pr->link; 
78.  } 
79.  return(l); 
80.} 
81.
82.char disp(PCB * pr) /*建立进程显示函数,用于显示当前进程*/ 
83.{ 
84.  printf("\n qname \t state \t nice \tndtime\truntime \n"); 
85.  printf("%s\t",pr->name); 
86.  printf("%c\t",pr->state); 
87.  printf("%d\t",pr->nice); 
88.  printf("%d\t",pr->ntime); 
89.  printf("%d\t",pr->rtime); 
90.  printf("\n"); 
91.}
92.
93.char check() /* 建立进程查看函数 */ 
94.{ 
95.  PCB* pr; 
96.  printf("\n **** 当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/ 
97.  disp(p); //显示进程信息
98.  pr=ready; 
99.  if (pr!=NULL) 
100.    printf("\n ****当前就绪队列状态为:"); /*显示就绪队列状态*/
101.  else 
102.    printf("\n ****当前就绪队列状态为: 空\n"); /*显示就绪队列状态为空*/
103.  while(pr!=NULL) 
104.  { 
105.    disp(pr); 
106.    pr=pr->link; 
107.  } 
108.} 
109.
110.char destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/ 
111.{ 
112.  printf(" 进程 [%s] 已完成.\n",p->name); 
113.  free(p); 
114.}
115. 
116.char running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/ 
117.{ 
118.  (p->rtime)++; //运行时间增加
119.  if(p->rtime==p->ntime) //达到要求的时间
120.  destroy(); //完成进程并释放
121.  else 
122.  { 
123.    (p->nice)--; //优先级减少
124.    p->state='W'; //改状态
125.    sort(); //按优先级重新排序
126.  } 
127.} 
128.
129.int main() /*主函数*/ 
130.{ 
131.  int len,h=0; 
132.  char ch; 
133.  input(); 
134.  len=space(); //链表长度
135.  while((len!=0)&&(ready!=NULL)) //只要队列不空
136.  { 
137.    ch=getchar(); 
138.    h++; 
139.    printf("\n The execute number:%d \n",h); //输出当前正在处理的进程号
140.    p=ready; //换到下一个结点
141.    ready=p->link; //记录下一个结点
142.    p->link=NULL; //删除连接
143.    p->state='R'; //更新状态
144.    check(); //展示进程数
145.    running(); //运行进程
146.    printf("\n按任一键继续......"); 
147.    ch=getchar(); 
148.  } 
149.  printf("\n\n 所有进程已经运行完成!\n"); 
150.  ch=getchar(); 
151.}

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

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

相关文章

Java项目:基于springboot实现的OA协同办公系统(源码+数据库+毕业论文)

一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…

matplotlib系统学习记录

日期&#xff1a;2024.03.12 内容&#xff1a;将matplotlib的常用方法做一个记录&#xff0c;方便后续查找。 基本使用 # demo01 from matplotlib import pyplot as plt # 设置图片大小,也就是画布大小 fig plt.figure(figsize(20,8),dpi80)#图片大小&#xff0c;清晰度# 准…

AssetBundle打包与加载

官方文档 参照视频 1.AssetBundle打包 1.1设置资源的命名和后缀 命名只支持小写 1.2创建Editor文件夹&#xff0c;在里面创建编辑器打包AssetBundle的脚本 using UnityEditor; using System.IO;public class CreateAssetBundles {[MenuItem("Assets/Build AssetBun…

Linux:好用的Linux指令

进程的Linux指令 1.查看进程信息 ​​​​ps ajx | head -1 && ps ajx | grep 进程名创建一个进程后输入上述代码&#xff0c;会打印进程信息&#xff0c;当我们在code.exe中写入打印pid&#xff0c;ppid&#xff0c;这里也和进程信息一致。 while :; do ps ajx | he…

力扣日记3.8-【回溯算法篇】37. 解数独

力扣日记&#xff1a;【回溯算法篇】37. 解数独 日期&#xff1a;2023.3.8 参考&#xff1a;代码随想录、力扣 37. 解数独 题目描述 难度&#xff1a;困难 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只…

上位机图像处理和嵌入式模块部署(qmacvisual串口输出结果)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们谈到了图像的输入、算法的添加&#xff0c;一切看上去都没有问题。但是这中间缺少了一个重要的环节&#xff0c;那就是结果的输出。如果我…

Java中的参数传递

程序设计语言将实参传递给方法&#xff08;或函数&#xff09;的方式分为两种&#xff1a; 值传递&#xff1a;方法接收的是实参值的拷贝&#xff0c;会创建副本。引用传递&#xff1a;方法接收的直接是实参所引用的对象在堆中的地址&#xff0c;不会创建副本&#xff0c;对形…

一文掌握mysql中的查询语句

目录 1. 聚合查询1.1 聚合函数1.2 GROUP BY子句1.3 HAVING 2. 联合查询2.1 内连接2.2 外连接2.3 自连接2.4 子查询2.5 合并查询 1. 聚合查询 1.1 聚合函数 常见的统计总数、计算平局值等操作&#xff0c;可以使用聚合函数来实现&#xff0c;常见的聚合函数有&#xff1a; 函…

Ubuntu 基本操作-嵌入式 Linux 入门

在 Ubuntu 基本操作 里面基本就分为两部分&#xff1a; 安装 VMware 运行 Ubuntu熟悉 Ubuntu 的各种操作、命令 如果你对 Ubuntu 比较熟悉的话&#xff0c;安装完 VMware 运行 Ubuntu 之后就可以来学习下一章节了。 1. 安装 VMware 运行 Ubuntu 我们首先来看看怎么去安装 V…

[MYSQL数据库]--表内操作(CURD)

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、表的 Cre…

【rk3368 android6.0 恢复出厂设置功能】

rk3368 android6.0 恢复出厂设置功能 恢复出厂设置三种方法一&#xff0c;设置--进入恢复出厂设置页面二&#xff0c;发送广播形式三&#xff0c;命令形式总结 郑重声明:本人原创博文&#xff0c;都是实战&#xff0c;均经过实际项目验证出货的 转载请标明出处:攻城狮2015 恢复…

视频素材网站哪个好?推荐几个高清无水印的短视频素材网

小伙伴们&#xff0c;如果你也是短视频的狂热爱好者&#xff0c;想要制作出优质满分的短视频作品&#xff0c;但苦于不知道从哪儿搞来那些高清无水印的素材&#xff0c;那今天你就来对地方啦&#xff01;我这里有几个绝佳的素材网站推荐给你&#xff0c;让你的创作源源不断。 …

Kubernetes kafka系列 | k8s部署kafka+zookeepe集群(可外部通信)| kafka docekr镜像制作-v3.5.2

一、 Kafka、ZooKeeper 的分布式消息队列系统总体架构 典型的 Kafka 体系架构包括若干 Producer(消息生产者),若干 Broker(作为 Kafka 节点的服务器),若干 Consumer (Group),以及一个 ZooKeeper 集群。 Kafka 通过 ZooKeeper 管理集群配置、选举 Leader,并在 Consum…

自动化运维工具 ---------------Ansible

一、Ansible 发展史及功能 作者&#xff1a;Michael DeHaan&#xff08; Cobbler pxe kikstar 与 Func 作者&#xff09;ansible 的名称来自科幻小说《安德的游戏》中跨越时空的即时通信工具&#xff0c;使用它可以在相距数光年的距离&#xff0c;远程实时控制前线的舰队战斗2…

AI人员睡岗识别摄像机

近年来&#xff0c;随着人工智能技术的不断发展&#xff0c;智能监控系统也得到了广泛应用。其中&#xff0c;AI人员睡岗识别摄像机作为一种新型的智能监控设备&#xff0c;正在逐渐受到企业和机构的关注和使用。这种摄像机利用人工智能技术&#xff0c;能够实时监测和识别工作…

智能指针的讲解

1.为什么要智能指针 首先我们分析一段代码&#xff1a; 1、如果p1这里new 抛异常会如何&#xff1f; 2、如果p2这里new 抛异常会如何&#xff1f; 3、如果div调用这里又会抛异常会如何&#xff1f; int div() {int a, b;cin >> a >> b;if (b 0)throw invalid_ar…

别再写传统简历了!AI简历5个超实用的功能,助你求职一臂之力(强烈建议收藏)

你们在制作简历时,是不是基本只关注两件事:简历模板,还有基本信息的填写。 当你再次坐下来更新你的简历时,可能会发现自己不自觉地选择了那个“看起来最好看的模板”,填写基本信息,却没有深入思考如何使简历更具吸引力。这其实是一个普遍现象:许多求职者仍停留在传统简历…

使用Julia语言展示几何平均值与算数平均值在实际应用中的差别(采用注册计量师考试试题)

理论部分 在注册计量师考试中有一道试题&#xff0c;大体内容为&#xff1a; 现在有一块砝码在等臂天平上进行测量&#xff0c;第一次测得值是19.6g&#xff0c;调换两边位置后的测得值是19.7g&#xff0c; 天平最终测得检测样品的重量为多少&#xff1f; 个别同事可能会将算…

每日一题leetcode -299.猜数字游戏

水一期 class Solution { public:string getHint(string secret, string guess) {int bulls 0;vector<int> cntS(10), cntG(10);for (int i 0; i < secret.length(); i) {if (secret[i] guess[i]) {bulls;} else {cntS[secret[i] - 0];cntG[guess[i] - 0];}}int c…

蓝桥杯真题讲解:三国游戏(贪心)

蓝桥杯真题讲解&#xff1a;三国游戏&#xff08;贪心&#xff09; 一、视频讲解二、正解代码 一、视频讲解 蓝桥杯真题讲解&#xff1a;三国游戏&#xff08;贪心&#xff09; 二、正解代码 //三国游戏&#xff1a;贪心 #include<bits/stdc.h> #define int long lon…