Linux程序设计上机指导书3:Linux进程控制
Linux进程控制

exec与fork配合使用的效率问题
• 在Unix时代exec经常与fork配合使用,但这样做了大 量的无用功,效率低下(为什么?)。
// 父进程做其他事情 return 0; }
exec函数族
exec函数族使用区别
• exec函数族使用区别
– 查找方式 • 表中的前四个函数的查找方式都是完整的文件目录路径,而最 后两个函数(以p结尾的函数)可以只给出文件名,系统就会自动 从环境变量“$PATH”所指出的路径中进行查找。
– 参数传递方式 • 两种方式:逐个列举、将所有参数整体构造指针数组传递 • 以函数名的第五位字母来区分的,字母为“l”(list)的表示逐个 列举的方式,其语法为char *arg;字母为“v”(vertor)的表示 将所有参数整体构造指针数组传递,其语法为*const argv[]
Fork函数的应用逻辑—孙悟空逻辑
int main() {
… …. // 遇到两个需要并行执行的任务:任务1和任务2 pid = fork(); // 分身术 if (pid == 0) { …… // 子进程处理任务1 } else { …… // 父进程处理任务2 } return 0; }
Fork函数应用例1
Linux进程状态
• Linux中任务和进程是相同的术语,每个进程由 task_struct 结构来描述,即PCB (进程控制块)
• Linux 将进程状态主要分为五种: – TASK_RUNNING – TASK_INTERRUPTIBLE – TASK_UNINTERRUPTIBLE – TASK_STOPPED /TASK_TRACED – TASK_ZOMBILE 。
Linux程序设计实验指导书

Linux程序设计实验指导书10/ 1前言根据教学大纲与实验大纲的安排,本课程计划进行8课时上机试验。
由于所有实验均涉及操作系统、程序设计等课程的多个知识点,希望各位同学认真准备。
?上机实验前应充分做好以下准备工作:1.复习和掌握与本次实验有关的教学内容。
2.根据本次实验的内容,在纸上编写好准备上机调试的程序,并初步检查无误。
3.准备好对程序进行测试的数据。
4.对每种测试数据,给出预期的程序运行结果。
5.预习实验步骤,对实验步骤中提出的一些问题进行思考。
?上机实验后,应及时写出实验报告,实验报告应包括以下内容:1.实验目的和内容。
2.程序说明,包括程序结构、各模块的算法。
3.调试正确的源程序。
4.程序运行记录(包括对不同测试数据的运行结果)。
5.针对实验中出现的问题,写出解决办法及对运行结果的分析。
本指导书适用于物联网工程专业学生学习“Linux程序设计”课程时实验使用。
10/ I.实验一:熟悉Linux实验学时:2实验类型:(验证)实验要求:(必修)一、实验目的Linux操作系统是多任务操作系统,对进程与线程提供完整支持。
本次实验意图通过实践掌握进程的基本概念,理解进程控制、进程同步、经典进程的同步问题、管程机制、进程通信、线程;初步熟悉多进程/多线程编程的特点。
Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。
它能运行主要的UNIX工具软件、应用程序和网络协议。
它支持32位和64位硬件。
Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。
本次实验意图通过实践了解Linux环境中常见的终端命令;熟悉文本编辑器leafpad 的使用。
二、实验内容本次实验的实验内容包括:1)熟悉man、cd、mkdir、rmdir、chmod、chown、ps、cat、ls命令;2) 练习使用文本编辑器leafpad。
使用Linux终端管理进程和任务

使用Linux终端管理进程和任务Linux终端是一种强大的工具,可以用来管理和监控系统中运行的进程和任务。
本文将介绍如何使用Linux终端来管理进程和任务,以提升系统性能和效率。
一、查看进程在Linux终端中,可以使用ps命令来查看系统中正在运行的进程。
ps命令有多种不同的选项,可以根据需求选择不同的选项来获取进程的详细信息。
1. ps aux该命令可以显示系统中所有用户的进程信息,并以列表形式进行展示。
每个进程的信息包括进程ID(PID)、CPU使用率、内存占用、进程状态等。
例如:```$ ps aux```2. ps -ef该命令显示所有进程的完整信息,包括进程之间的父子关系。
例如:```$ ps -ef```3. ps -u该命令可以按照用户名来筛选进程,并只显示该用户的进程信息。
例如:```$ ps -u username```二、管理进程在Linux终端中,可以使用kill命令来终止运行中的进程。
kill命令可以接受进程ID作为参数,或者使用进程名称来终止进程。
1. 终止进程使用kill命令终止进程时,需要指定进程的PID。
例如,要终止进程ID为123的进程,可以使用以下命令:```$ kill 123```2. 强制终止进程有时候进程可能无法正常终止,这时可以使用kill命令的-9选项强制终止进程。
例如:```$ kill -9 123```三、任务管理除了进程管理,Linux终端还可以方便地管理系统中的任务。
任务是指在终端中运行的命令或程序。
1. 后台运行任务在Linux终端中,可以使用&符号将任务放入后台运行。
例如,要在后台运行一个脚本文件,可以使用以下命令:```$ ./script.sh &```2. 列出后台任务使用jobs命令可以列出当前终端中所有正在运行的后台任务。
例如:```$ jobs```3. 暂停和恢复任务使用Ctrl+Z组合键可以将当前正在运行的任务暂停,使用fg命令可以将任务从后台恢复到前台运行。
Linux C第3次上机作业(进程控制)

#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid,int *status,int options);
pid参数
1. pid>0时,只等待进程ID等于pid的子进程,不管 其它已经有多少子进程运行结束退出了,只要指定 的子进程还没有结束,waitpid就会一直等下去。 2. pid=-1时,等待任何一个子进程退出,没有任何 限制,此时waitpid和wait的作用一模一样。 3. pid=0时,等待同一个进程组中的任何子进程, 如果子进程已经加入了别的进程组,waitpid不会对 它做任何理睬。 4. pid<-1时,等待一个指定进程组中的任何子进程 ,这个进程组的ID等于pid的绝对值。
options参数
options提供了一些额外的选项来控制waitpid,目 前在Linux中只支持WNOHANG和WUNTRACED两个选项, 这是两个常数,可以用“|”运算符把它们连接起来 使用,如:
ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);
如果我们不想使用它们,也可以把options设为0
当pid所指示的子进程不存在,或此进程存在,但 不是调用进程的子进程,waitpid就会出错返回。子进程显示自己的进程 号(PID)后暂停一段时间(10秒),父进程等待子进程正常 结束,打印显示等待的进程号(PID)。(分别用wait函数和 waitpid函数实现)。 2.设计一个程序,创建子进程,子进程在运行时执行vim程 序,并查看程序的进程号与vim的进程号。(用system函 数族实现)(vim在user/bin目录下)
1、WIFEXITED(status) 这个宏用来指出子进程是否为正常退出的,如果是, 它会返回一个非零值。 2、WEXITSTATUS(status) 当WIFEXITED返回非零值时,我们可以用这个宏 来提取子进程的返回值。
LINUX 的进程控制

printf(“I am parent, my rid is %d, my PID is %d\n”, rid, getpid()); else // 子进程分支
printf(“I am child, my rid is %d, my PID is %d\n”, rid, getpid()); }
注:程序中的getpid()是一个系统调用,它返回本进程 的进程标识号PID。 fork_test程序运行时,父子进程将会输出不同的信息, 如父进程的输出可能是“I am parent, my rid is 8229, my PID is 8228”;子进程的输出可能是“I am child, my rid is 0, my PID is 8229”。由于两进程是并发的,它们输出信息的先后 次序不确定,有可能父先子后,也可能相反。
与一般的函数不同,exec()是“一次调用,零次返回”, 因为调用成功后,进程的映像已经被替换,无处可以返回了。 图4-9描述了用exec()系统调用更换进程映像的流程。子进程 开始运行后,立即调用exec(),变身成功后即开始执行新的 程序了。
图4 用exec更换子进程的映像
例2 一个简单的fork-exec_test程序:
2) 终止进程 进程无论以哪种方式结束,都会调用一个exit()系统调 用,通过这个系统调用终止自己的运行,并及时通知父进程 回收本进程。exit()系统调用完成以下操作:释放进程除 PCB外的几乎所有资源;向PCB写入进程退出状态和一些统 计信息;置进程状态为“僵死态”;向父进程发送“子进程 终止(SIGCHLD)”信号;调用进程调度程序切换CPU的运行 进程。
若程序中不考虑fork()的返回值,则父子进程的行为就 完全一样了。但创建一个子进程的目的是想让它做另一件事。 所以,通常的做法是:在fork()调用后,通过判断fork()的返 回值,分别为父进程和子进程设计不同的执行分支。这样, 父子进程执行的虽是同一个代码,执行路线却分道扬镳。图 4-8描述了用fork()创建子进程的常用流程。
03_Linux进程控制_系统编程

LINUX进程控制1.Linux进程概述进程是一个程序一次执行的过程,是操作系统动态执行的基本单元。
进程的概念主要有两点:第一,进程是一个实体。
每个进程都有自己的虚拟地址空间,包括文本区、数据区、和堆栈区。
文本区域存储处理器执行的代码;数据区存储变量和动态分配的内存;堆栈区存储着活动进程调用的指令和本地变量。
第二,进程是一个“执行中的程序”,它和程序有本质区别。
程序是静态的,它是一些保存在磁盘上的指令的有序集合;而进程是一个动态的概念,它是一个运行着的程序,包含了进程的动态创建、调度和消亡的过程,是Linux的基本调度单位。
只有当处理器赋予程序生命时,它才能成为一个活动的实体,称之为进程。
内核的调度器负责在所有的进程间分配CPU执行时间,称为时间片(time slice),它轮流在每个进程分得的时间片用完后从进程那里抢回控制权。
1.1.进程标识OS会为每个进程分配一个唯一的整型ID,做为进程的标识号(pid)。
进程0是调度进程,常被成为交换进程,它不执行任何程序,是内核的一部分,因此也被成为系统进程。
进程除了自身的ID外,还有父进程ID(ppid)。
也就是说每个进程都必须有它的父进程,操作系统不会无缘无故产生一个新进程。
所有进程的祖先进程是同一个进程,它叫做init进程,ID为1,init进程是内核自举后的第一个启动的进程。
init进程负责引导系统、启动守护(后台)进程并且运行必要的程序。
它不是系统进程,但它以系统的超级用户特权运行。
1.2.进程的状态进程是程序的执行过程,根据它的生命周期可以划分成3种状态。
●执行态:该进程正在运行,即进程正在占用CPU。
●就绪态:进程已经具备执行的一切条件,正在等待分配CPU的处理时间片。
●等待态:进程不能使用CPU,若等待事件发生(等待的资源分配到)则可将其唤醒。
1.3.Linux下的进程结构及管理Linux系统是一个多进程的系统,它的进程之间具有并行性、互不干扰等特点。
Linux系统编程之进程控制(进程创建、终止、等待及替换)

Linux系统编程之进程控制(进程创建、终⽌、等待及替换)进程创建在上⼀节讲解进程概念时,我们提到fork函数是从已经存在的进程中创建⼀个新进程。
那么,系统是如何创建⼀个新进程的呢?这就需要我们更深⼊的剖析fork 函数。
1.1 fork函数的返回值调⽤fork创建进程时,原进程为⽗进程,新进程为⼦进程。
运⾏man fork后,我们可以看到如下信息:#include <unistd.h>pid_t fork(void);fork函数有两个返回值,⼦进程中返回0,⽗进程返回⼦进程pid,如果创建失败则返回-1。
实际上,当我们调⽤fork后,系统内核将会做:分配新的内存块和内核数据结构(如task_struct)给⼦进程将⽗进程的部分数据结构内容拷贝⾄⼦进程添加⼦进程到系统进程列表中fork返回,开始调度1.2 写时拷贝在创建进程的过程中,默认情况下,⽗⼦进程共享代码,但是数据是各⾃私有⼀份的。
如果⽗⼦只需要对数据进⾏读取,那么⼤多数的数据是不需要私有的。
这⾥有三点需要注意:第⼀,为什么⼦进程也会从fork之后开始执⾏?因为⽗⼦进程是共享代码的,在给⼦进程创建PCB时,⼦进程PCB中的⼤多数数据是⽗进程的拷贝,这⾥⾯就包括了程序计数器(PC)。
由于PC中的数据是即将执⾏的下⼀条指令的地址,所以当fork返回之后,⼦进程会和⽗进程⼀样,都执⾏fork之后的代码。
第⼆,创建进程时,⼦进程需要拷贝⽗进程所有的数据吗?⽗进程的数据有很多,但并不是所有的数据都要⽴马使⽤,因此并不是所有的数据都进⾏拷贝。
⼀般情况下,只有当⽗进程或者⼦进程对某些数据进⾏写操作时,操作系统才会从内存中申请内存块,将新的数据拷写⼊申请的内存块中,并且更改页表对应的页表项,这就是写时拷贝。
原理如下图所⽰:第三,为什么数据要各⾃私有?这是因为进程具有独⽴性,每个进程的运⾏不能⼲扰彼此。
1.3 fork函数的⽤法及其调⽤失败的原因fork函数的⽤法:⼀个⽗进程希望复制⾃⼰,通过条件判断,使⽗⼦进程分流同时执⾏不同的代码段。
实验三 Linux进程的创建与控制

printf(“child %d\n”,i);
lockf(1,0,0);/解锁/
}
else
{
while((p2=fork())= =-1);
if(p2= =0)
{
lockf(1,1,0);
for(i=0;i<20;i++)
printf(“son %d\n”,i);
lockf(1,0,0);
}
else
{
lockf(1,1,0);
for(i=0;i<20;i++)
printf(“daughter %d\n”,i);
lockf(1,0,0);
}
}
}
思考问题:
(1)系统是怎样创建进程的?
(2)当首次调用新创建进程时,其入口在哪里?
while((p1=fork())= =-1);
if(p1= =0)
for(i=0;i<20;i++)
printf(“Child %d\n”,i);
else
{
while((p2=fork() )= =-1);
if(p2= =0)
for(i=0;i<20;i++)
printf(“Son %d\n”,i)
else
for(i=0;i<20;i++)
printf(“Daughter %d\n”,i);
}
}
程序2:
#include <stdio.h>
#include <unistd.h>
main()
Linux系统编程——进程控制

Linux系统编程——进程控制在学习Linux系统编程总结了笔记,并分享出来。
有问题请及时联系博主:,转载请注明出处。
09-linux-day05(进程控制)⽬录:⼀、学习⽬标⼆、进程1、进程和程序2、单道和多道程序设计3、进程的状态转化4、MMU 的作⽤5、PCB的概念6、获取环境变量7、进程控制函数fork8、fork创建⼦进程9、进程控制的命令10、创建n个⼦进程11、循环创建n个⼦进程控制顺序12、⽗⼦进程共享的内容13、⽗⼦进程不共享全局变量14、execlp函数介绍15、exec函数规律16、exel实现⾃定义程序17、孤⼉进程与僵⼫进程18、wait函数简单使⽤和说明19、wait回收并且查看死亡原因20、waitpid回收⼦进程21、⽤wait回收多个⼦进程22、waitpid回收多个⼦进程⼀、学习⽬标1、了解进程相关的概念2、掌握fork/getpid/getppid函数的使⽤3、熟练掌握ps/kill命令的使⽤4、熟练掌握execl/execlp函数的使⽤5、说出什么是孤⼉进程什么是僵⼫进程6、熟练掌握wait函数的使⽤7、熟练掌握waitpid函数的使⽤⼆、进程1、进程和程序什么是程序?编译好的⼆进制⽂件。
什么是进程?运⾏着的程序。
站在程序员的⾓度:运⾏⼀系列指令的过程。
站在操作系统⾓度:分配系统资源的基本单位。
区别: 程序占⽤磁盘,不占⽤系统资源。
进程占⽤系统资源。
⼀个程序对应多个进程,⼀个进程对应⼀个程序。
程序没有⽣命周期,进程有⽣命周期。
2、单道和多道程序设计3、进程的状态转化进程的状态切换4、MMU 的作⽤》MMU作⽤:1)虚拟内存和物理内存的映射;2)修改内存访问级别⽤户空间映射到物理内存是独⽴的。
5、PCB的概念Linux内核的进程控制块是task_struct结构体。
查找结构体:> sudo grep -rn "struct task_struct {" /usr/技巧:光标停留在{上,按%,可以到结构体的结尾。
LINUX实验三指导书—Linux进程控制与通信(计算机)(3课时)

实验三 进程控制与通信一、【实验目的】1、加深进程控制和进程通信的基本原理2、熟练使用Linux 系统下进程控制、进程通信、信号量的系统函数二、【实验内容】1、进程并发图如图1所示:设有7个进程,其执行次序如图7-1所示。
在Linux 中中使用C 语言利用系统调用命令fork(),execl(),exit(),wait()进程描述,调用execl()函数的时候,模拟调用/bin/echo 命令,向控制台输出依据可鉴别是哪个进程的字符串即可。
P1P1P2P2P3P3P4P4P5P5P6P6P7P7图1 进程并发图2、利用LINUX 通信机制,实现输入字符串的自动分流操作。
其中通信方式自选,下面的问题描述以管道为例,示意图如图2;一共涉及3个管道,4个进程。
● P1:从键盘接收输入字符串,写入管道pipe1● P2:从ipe1接收字符串,若字符串的长度为偶数,则将其写入管道 pipe2中,否则将其写入管道pipe3中.● P3:从pipe2中读出字符串,并显示"pipe2: Even length string" ● P4: 从pipe3中读出字符串,并显示"pipe3: Odd length string" 输入exit 程序退出。
P1P1图2 管道示意图3、利用LINUX信号量操作实现读者-写者问题。
问题如下:有一个初始化的数组,读者进程和写者进程均是对此数组进行操作。
读者读出数组的数字,读出位置随机设定。
写者是随机对数组中的数字进行修改,修改的值也是随机的。
读写请求随机产生(比如按键盘上的R和W键),并动态显示当前的状态(读的时候有多少读者,有多少个写者在等待;写的时候是谁在写,还有多少写者和读者在等待)。
每个读者和写者用的时间可以预先设定。
互斥约束是:读-读、读-写、写-写都互斥(做成只有读-写、写-写互斥也可以)。
4.(选做)基于SOCKET的通信程序(1)在同一台机器上建立一个服务器端Server和一个客户端Client(2)建立Server与Client的连接(3)Server提供一个计算功能,即进行四则运算(除号用“/"代替)。
请简述 linux 中的进程处理和控制方式。

请简述 linux 中的进程处理和控制方式。
Linux 中的进程处理和控制方式主要包括以下几种:
1. 创建进程:Linux 中可以通过系统调用 `fork()` 来创建新的进程,`fork()` 会创建一个当前进程的副本,并在新进程中执行。
另外还可以使用 `exec()` 系列函数来执行新的程序,并替换当前进程。
2. 进程状态:Linux 中的进程状态包括运行态、就绪态、阻塞态和退出态。
运行态表示进程当前正在执行;就绪态表示进程已经准备好执行,但还没被调度;阻塞态表示进程由于某些原因无法执行,比如等待 I/O 操作完成;退出态表示进程已经执行完毕。
3. 进程调度:Linux 使用时间片轮转的方式进行进程调度。
每个进程被分配一定的时间片,在时间片用完后会被挂起,然后调度器选择下一个就绪态的进程运行。
4. 进程间通信:Linux 提供了多种进程间通信的方式,包括管道、命名管道、信号量、共享内存、套接字等。
这些机制允许进程之间进行数据传递和同步操作。
5. 进程控制:通过系统调用可以对进程进行控制,包括暂停进程、恢复进程、终止进程等操作。
通过信号可以向进程发送中断或其他事件通知。
6. 进程资源限制:Linux 中可以通过 `rlimit` 结构体来设置和
获取进程的资源限制,比如 CPU 时间限制、内存限制、文件打开数限制等。
总之,Linux 中的进程处理和控制方式非常强大和灵活,可以通过系统调用和信号等机制来管理和控制进程的创建、调度、通信和资源限制等。
linux 中的进程处理和控制方式

linux 中的进程处理和控制方式Linux 是一种广泛使用的操作系统,它具有强大的进程处理和控制功能。
在 Linux 系统中,进程是进行任务的基本单位,它们可以同时运行,互相通信,共享资源,因此进程处理和控制是 Linux 系统重要的组成部分。
Linux 提供了多种方式来处理和控制进程。
以下是一些常见的方式:1. 创建新进程:在 Linux 系统中,可以通过 fork() 系统调用创建一个新的子进程。
子进程是通过复制父进程的内存空间、文件描述符和其他资源来创建的。
这样可以实现并行处理任务,提高系统的效率。
创建新进程时,可以使用 exec() 系统调用来加载一个新的程序运行。
2. 进程调度:Linux 使用调度器(scheduler)来决定哪个进程在何时执行。
调度算法会根据进程的优先级(priority)和调度策略来决定进程的执行顺序。
常见的调度策略包括先进先出(FIFO)、最短作业优先(SJF)、轮转(Round Robin)等。
通过合理的调度算法,可以提高系统的响应速度和资源利用率。
3. 进程间通信:在 Linux 中,进程之间可以通过多种方式进行通信。
其中最常用的方式是通过管道(pipe)、信号(signal)和共享内存(shared memory)来进行进程间的数据交换。
管道可以实现进程的单向通信,信号可以用于进程之间的异步通信,而共享内存可以让多个进程共享同一片内存区域,实现高效的数据交换。
4. 进程控制:Linux 提供了多个命令和系统调用来控制进程的行为。
例如,可以使用 ps 命令来查看系统中正在运行的进程,使用kill 命令发送信号终止进程,使用 nice 命令来改变进程的优先级等。
此外,还可以使用进程控制信号(Process Control Signals)来改变进程的状态,如暂停、继续、停止等。
5. 进程管理工具:Linux 提供了一些进程管理工具来帮助用户更方便地处理和控制进程。
Linux命令行中的进程资源限制和控制技巧

Linux命令行中的进程资源限制和控制技巧在Linux操作系统中,进程资源限制和控制是系统管理员和开发人员必须掌握的重要技巧之一。
通过适当的资源限制和控制,我们可以确保系统的稳定性、安全性和性能。
本文将介绍Linux命令行中常用的进程资源限制和控制技巧,帮助读者更好地管理和优化系统。
一、ulimit命令ulimit是Linux系统用来限制进程资源的命令。
通过ulimit命令,我们可以设置和查询不同资源的限制参数。
下面是ulimit命令的一些常见用法:1. 设置进程可以打开的文件描述符的最大数量:ulimit -n 8192以上命令将设置当前进程可以打开的文件描述符的最大数量为8192。
这对于需要同时处理大量文件的应用程序非常有用。
2. 设置core文件的大小限制:ulimit -c unlimited以上命令将设置core文件的大小限制为无限制。
当程序发生崩溃时,core文件可以帮助开发人员进行调试和分析。
3. 设置进程的CPU时间限制:ulimit -t 3600以上命令将设置当前进程的CPU时间限制为3600秒。
这对于防止某个进程占用过多的CPU资源非常有用。
二、nice和renice命令nice和renice命令是用来控制进程优先级的命令。
通过调整进程的优先级,我们可以确保重要的进程获得更多的系统资源。
以下是nice 和renice命令的一些用法:1. 前台命令设置优先级:nice -n 10 command以上命令将执行command命令,并设置其优先级为10。
优先级范围为-20到19,数值越小优先级越高。
2. 修改已运行进程的优先级:renice -n 5 pid以上命令将修改进程pid的优先级为5。
使用top命令可以查看进程的pid。
三、cpulimit命令cpulimit命令用于限制进程的CPU使用率。
通过限制进程的CPU使用率,我们可以避免某个进程占用过多的CPU资源,保证系统的稳定性。
Linux课程设计进程控制

课程设计报告课程名称Linux操作系统课程设计指导教师张玲起止日期2014-03-01 至2014-06-13实验项目实验二进程控制学院信息与通信工程学院专业电子信息工程学生姓名班级/学号成绩指导老师签字1. 课程设计概述本次课设意在利用进程控制相关的系统调用编程进行进程控制实验,观察进程从创建、运行到终止的控制过程,加深对进程概念的理解。
1.1 课程设计的目的本实验的目的是掌握进程的概念,理解进程的创建、执行、等待、终止的过程。
熟悉有关进程控制的命令和系统调用,理解Shell 的工作原理。
1.2 课程设计的内容1) 进程控制命令● 使用进程控制命令ps ,kill 监视和控制进程的活动2) 编程部分● 用fork ,wait ,exec 系统调用编程实现进程控制;● 编写一个简单的shell 。
1.3 设计原理进程是一个其中运行着一个或多个线程的地址空间和这些线程所需要的系统资源。
构建的文件构架如图:图1 实验目录树的结构 2012010948exp2 exp1 exp3vis vis22.实验步骤2.1操作2.1.1进程控制命令(在此终端窗口的操作截图见图1)1.执行ps命令,查看bash进程的PID:PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID。
进程中止后PID被系统回收。
2.在后台运行一个yes进程:yes > /dev/null &3.用ps -f命令观察yes进程的pid和ppid,用ps u命令观察yes进程的状态。
yes进程的父进程是哪个进程?通过查看yes程序的PPID可知其父进程为bash4.根据命令名搜索特定的进程:ps-ef|grep yes:5.用kill命令杀掉yes进程:kill 【PID】:图1 进程控制命令2.1.2进程控制系统调用(此部分操作截图见图2、3)1.利用fork()和wait()来控制进程的执行:♦在exp2目录下编写一个程序fork_wait.c。
Linux的进程控制

6.2.4 僵尸进程
编辑源程序代码:
此例中的子进程运行时间,明显 比父进程时间长。为了避免子进 程成为僵尸进程,父进程调用 wait,阻塞父进程的运行,等待 子进程正常结束,父进程才继续 运行,直到正常结束。
29
wait函数说明
30
6.2.4 僵尸进程
例6-7:设计一个程序,要求用户可以选择 是否复制进程,子进程模仿思科 (Cisco)1912交换机的开机界面,以命令行 的方式让用户选择进入,父进程判断子进 程是否正常终止。 流程图:
请编写并进行调试。
23
6.2.3 进程终止
滥用fork函数会占满系统进程,而且子进程 与父进程使用不同的内存空间,不断产生 子进程,也可能让系统资源消耗殆尽。 Linux环境下c终止进程主要用exit和_exit函 数。
观察结果可以看出,调
例6-5:设计一个程序,要求用e子xit进函数程时和,父缓冲进区
waitpid的作用和wait一样,但它并不一定要等待第一个终 止的子进程,它还有若干选项,也能支持作业控制。
实际上wait函数只是waitpid函数的一个特例,在Linux内部 实现wait函数时直接调用的就是waitpid函数。
27
6.2.4 僵尸进程
例6-6:设计一个程序,要求复制进程,子 进程显示自己的进程号(PID)后暂停一段时 间,父进程等待子进程正常结束,打印显 示等待的进程号(PID)和等待的进程退出状 态。 流程图:
33
waitpid函数说明
34
3 Linux守护进程
守护进程(Daemon)是运行在后台的一种 特殊进程。 守护进程独立于控制终端并且周期性地执 行某种任务或等待处理某些发生的事件。 守护进程是一种很有用的进程。Linux的大 多数服务器就是用守护进程实现的。 同时,守护进程完成许多系统任务。
Linux程序设计上机指导书3:Linux进程控制

Linux程序设计上机指导书3:Linux进程控制上机三:Linux进程控制1.⽬的(1)掌握系统调⽤fork(),exex(),exit()等实现进程创建;(2)掌握进程的终⽌⽅式(return、exit、_exit、abort);(3)掌握僵⼫进程的产⽣和避免,以及wait,waitpid的使⽤;(4)了解守护进程的创建。
2.内容主要上机分析代码⽂件。
systemtest.c6-3.c6-4.c6-8.c6-9.c其他略。
3.步骤1)Linux进程的创建创建进程可以采⽤⼏种⽅式。
可以执⾏⼀个程序(这会导致新进程的创建),也可以在程序内调⽤⼀个fork 或exec来创建新进程。
fork 调⽤会导致创建⼀个⼦进程,⽽exec 调⽤则会⽤新程序代替当前进程上下⽂。
exec系列函数并不创建新进程,调⽤exec前后的进程ID是相同的。
exec函数的主要⼯作是清除⽗进程的可执⾏代码映像,⽤新程序的代码覆盖调⽤exec 的进程代码。
如果exec执⾏成功,进程将从新程序的main函数⼊⼝开始执⾏。
调⽤exec 后,除进程ID保持不变外,还有下列进程属性也保持不变。
(1)进程的⽗进程ID。
(2)实际⽤户ID和实际⽤户组ID。
(3)进程组ID、会话ID和控制终端。
(4)定时器的剩余时间。
(5)当前⼯作⽬录及根⽬录。
(6)⽂件创建掩码UMASK。
(7)进程的信号掩码。
与exec系统调⽤不同,system将外部可执⾏程序加载执⾏完毕后继续返回调⽤进程。
【例6.3】设计⼀个程序,⽤fork函数创建⼀个⼦进程,在⼦进程中,要求显⽰⼦进程号与⽗进程号,然后显⽰当前⽬录下的⽂件信息,在⽗进程中同样显⽰⼦进程号与⽗进程号。
/*6-3.c 将⼀个进程分为两个⼀样的进程,打印出进程的相关信息*/#include /*⽂件预处理,包含标准输⼊输出库*/#include /*⽂件预处理,包含system、exit等函数库*/#include /*⽂件预处理,包含fork、getpid、getppid函数库*/#include /*⽂件预处理,包含fork函数库*/int main () /*C程序的主函数,开始⼊⼝*/{pid_t result;result=fork(); /*调⽤fork函数,返回值存在变量result中*/int newret;if(result==-1) /*通过result的值来判断fork函数的返回情况,这⼉先进⾏出错处理*/ {perror("创建⼦进程失败");exit(0);}else if (result==0) /*返回值为0代表⼦进程*/{printf("返回值是:%d,说明这是⼦进程!\n此进程的进程号(PID)是:%d\n此进程的⽗进程号(PPID)是:%d\n",result,getpid(),getppid());execl(“/bin/ls”,”ls”,”-l”,0); /*调⽤ls程序,显⽰当前⽬录下的⽂件信息*/ }else /*返回值⼤于0代表⽗进程*/【步骤1】设计编辑源程序代码。
Linux进程控制

1.进程的创建与调度执行
不同的操作系统所提供的进程创建原语的名称和格式不尽相同,但执行创 建进程原语后,操作系统所做的工作却大致相同,都包括以下几点:
➢ 给新创建的进程分配一个内部标识,并分配一个空白的PCB,同时在系 统进程表中增加一个表目。
➢ 为该进程分配内存空间,包括进程映像所需要的所有元素(程序、数据、 用户栈等),复制父进程内存空间的内容到该进程内存空间中。
2021/5/4
3
Linux中用户子进程的创建与调度执行
用户可以在自己的进程中创建多个子进程以实现多个不同任 务 的 并 发 执 行 。 Linux 提 供 的 创 建 子 进 程 的 系 统 调 用 是 fork()。
格式: int fork( )
返回值: =0 创建成功,从子进程返回;
>0 创建成功,从父进程返回,其值为子进程的PID号;
投入运行。
2021/5/4
19
进程睡眠
2.Linux中进程的睡眠
Linux提供多种可能导致进程睡眠或等待的系统调用,本 章主要介绍父进程等待子进程终止的系统调用wait()和 进程延时系统调用sleep()。wait()的使用格式在3.5.2节 中介绍。此处介绍进程延时sleep()。
➢ 进程请求延时。
2021/5/4
18
进程睡眠
操作系统提供一系列系统调用函数,提供进程针对不同的请求加以调用。 当进程使用了其中的一个函数调用后,其申请的条件得不到满足或者 请求的服务是I/O时,该进程就会自动进入睡眠状态。而进程一旦进入 睡眠状态,则只能由其它进程将其唤醒。
假设引起睡眠的原因为chan,进程睡眠原语执行后操作系统要作如下工作: ⑴.将当前需要睡眠的进程运行现场保护到其PCB中; ⑵.置进程的状态为阻塞态; ⑶.将该进程插入引起睡眠的chan的等待队列; ⑷.转进程调度。因为此时CPU空闲,需激活调度进程以调度另一个进程
第4章 Linux进程控制

state prio pid tgid pgrp sessin thread_info run_list
指向进程队列
thread_info
进程亲属关系的字段
指向当前目录的指针 指向文件描述符的指针 指向主存描述符的指针 指向信号结构的指针 指向tty结构的指针
real_paren parent t children sibling fs files mm signal tty
进程基本信息 每个进程都有一个进程基本信息块。在进程 描述符的thread_info字段中包含了指向该结 构的指针 与进程调度有关的信息 根据进程优先级把进程组织成多个队列,最 多可有140个。 进程的亲属关系 :进程描述符中的亲属关系 字段
字段名
说明
real_parent 指向创建p进程的父进程的描述符,若 该父进程不再存在,就指向1#进程 parent 指向p进程的当前父进程,它的值通常 与real_parent一致,偶尔也可不同 children 链表的头部,链表中的所有进程都是p 进程创建的子进程 sibling 指向兄弟进程链表中的下一个或前一个 元素的指针
fork创建新进程
为新进程生成task_struct结构 为新进程赋予一个统一的标识(PID) 为进程映像分配存储空间 将新进程插入就绪队列
16
#include <unistd.h>
#include <sys/types.h>
格式:pid_t fork( )
返回值:
=-1 创建失败
=0 创建成功,从子进程返回;
可能的状态 TASK_RUNNING (可运行状态)
进程是可执行的
它或者正在执行,运行状态
或者在运行队列中等待执行,就绪状态
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
上机三:Linux进程控制1.目的(1)掌握系统调用fork(),exex(),exit()等实现进程创建;(2)掌握进程的终止方式(return、exit、_exit、abort);(3)掌握僵尸进程的产生和避免,以及wait,waitpid的使用;(4)了解守护进程的创建。
2.内容主要上机分析代码文件。
systemtest.c6-3.c6-4.c6-8.c6-9.c其他略。
3.步骤1)Linux进程的创建创建进程可以采用几种方式。
可以执行一个程序(这会导致新进程的创建),也可以在程序内调用一个fork 或exec来创建新进程。
fork 调用会导致创建一个子进程,而exec 调用则会用新程序代替当前进程上下文。
exec系列函数并不创建新进程,调用exec前后的进程ID是相同的。
exec函数的主要工作是清除父进程的可执行代码映像,用新程序的代码覆盖调用exec 的进程代码。
如果exec执行成功,进程将从新程序的main函数入口开始执行。
调用exec 后,除进程ID保持不变外,还有下列进程属性也保持不变。
(1)进程的父进程ID。
(2)实际用户ID和实际用户组ID。
(3)进程组ID、会话ID和控制终端。
(4)定时器的剩余时间。
(5)当前工作目录及根目录。
(6)文件创建掩码UMASK。
(7)进程的信号掩码。
与exec系统调用不同,system将外部可执行程序加载执行完毕后继续返回调用进程。
【例6.3】设计一个程序,用fork函数创建一个子进程,在子进程中,要求显示子进程号与父进程号,然后显示当前目录下的文件信息,在父进程中同样显示子进程号与父进程号。
/*6-3.c 将一个进程分为两个一样的进程,打印出进程的相关信息*/#include<stdio.h> /*文件预处理,包含标准输入输出库*/#include<stdlib.h> /*文件预处理,包含system、exit等函数库*/#include<unistd.h> /*文件预处理,包含fork、getpid、getppid函数库*/#include<sys/types.h> /*文件预处理,包含fork函数库*/int main () /*C程序的主函数,开始入口*/{pid_t result;result=fork(); /*调用fork函数,返回值存在变量result中*/int newret;if(result==-1) /*通过result的值来判断fork函数的返回情况,这儿先进行出错处理*/ {perror("创建子进程失败");exit(0);}else if (result==0) /*返回值为0代表子进程*/{printf("返回值是:%d,说明这是子进程!\n此进程的进程号(PID)是:%d\n此进程的父进程号(PPID)是:%d\n",result,getpid(),getppid());execl(“/bin/ls”,”ls”,”-l”,0); /*调用ls程序,显示当前目录下的文件信息*/ }else /*返回值大于0代表父进程*/【步骤1】设计编辑源程序代码。
[root@localhost root]#vi 6-3.c【步骤2】用gcc编译程序。
[root@localhost root]#gcc 6-3.c –o 6-3【步骤3】运行程序。
编译成功后,执行6-3,此时系统会出现运行结果,根据result的值,先显示Linux系统分配给子进程的进程号(PID)和父进程号(PPID),接着运行ls程序,显示当前目录下的文件信息。
再等待10秒钟后,显示父进程的进程号(PID)和父进程号(PPID)。
【步骤4】在6-3.c代码中改变:execl(“/bin/ls”,”ls”,”-l”,0); /*调用ls程序,显示当前目录下的文件信息*/ 替换为:printf("执行前的进程号(PID)是:%d\n",getpid()); /*显示输出进程号*/printf("执行前的父进程号(PPID)是:%d\n",getppid());/*显示输出父进程号*/execv(“6-1”, NULL); /*调用6-1程序*/执行后观察进程的PID和PPID是否有改变。
2)Linux进程的终止(1) 正常终止:(a) 在main函数内执行return语句,这等效于调用exit。
(b) 调用exit函数。
此函数由ANSIC定义,其操作包括调用各终止处理程序,然后关闭所有标准I/O流等。
(c) 调用_exit系统调用函数,此函数由exit调用。
(2) 异常终止:(a) 调用abort 。
(b) 由一个信号终止。
exit, _exit, _Exit 都是进程终止函数。
abort产生SIGABRT 信号。
非正常退出,即在程序碰到灾难性错误时强制退出。
由于是非正常退出,因此不会做其它任何操作。
return与exit的区别在进程操作中exit是结束当前进程或程序并把控制权返回给调用该程序或者进程的进程即父进程并告诉父进程该当前进程的运行状态,而return是从当前函数返回,如果是在main 函数中,main函数结束时隐式地调用exit函数,自然也就结束了当前进程。
return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示了一个进程的结束。
exit函数是退出应用程序,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息。
在main函数里面return(0)和exit(0)是一样的,子函数用return返回;而子进程用exitint main () /*C程序的主函数,开始入口*/{pid_t result;result=fork(); /*调用fork函数,返回值存在变量result中*/if(result==-1) /*通过result的值来判断fork函数的返回情况,这儿先进行出错处理*/ {perror("创建子进程失败");exit(0);}else if (result==0) /*返回值为0代表子进程*/{printf("测试终止进程的_exit函数!\n");printf("目前为子进程,这一行我们用缓存!");_exit(0);}else /*返回值大于0代表父进程*/{printf("测试终止进程的exit函数!\n");printf("目前为父进程,这一行我们用缓存!");exit(0);}3)Linux的僵尸进程(wait/waitpid的使用)僵尸进程是指的父进程已经退出,父进程没有处理子进程的退出信息(包括子进程的返回值和其他的一些东西),使得已退出的子进程就成为僵尸进程Defunct ("zombie")。
僵尸进程只是在process table里有一个记录,没有占用其他的资源,除非系统的进程个数的限制已经快超过了,zombie进程不会有更多的坏处。
通过在父进程里增加一个wait/waitpid可以解决僵尸进程问题。
一般来说,当父进程fork()一个子进程后,它必须用wait() 或者waitpid() 等待子进程退出。
正是这个wait() 动作完全清除子进程退出后的信息。
【例题】设计一个程序,要求用户可以选择是否创建子进程,子进程模仿思科(Cisco)1912交换机的开机界面,以命令行的方式让用户选择进入,父进程判断子进程是否正常终止。
图1 算法流程/*6-8.c 创建进程(cisco菜单)*/#include<stdio.h> /*文件预处理,包含标准输入输出库*/#include<unistd.h> /*文件预处理,包含fork函数库*/#include<sys/types.h> /*文件预处理,包含fork、wait、waitpid函数库*/ #include<sys/wait.h> /*文件预处理,包含wait、waitpid函数库*/#include<stdlib.h> /*文件预处理,包含exit函数库*/void display0(); /*子程序声明*/void display1();void display2();int main () /*程序的主函数,开始入口*/{pid_t result;int status,select,num;void (*fun[3])(); /*利用函数指针建立三个子程序*/fun[0]=display0;fun[1]=display1;fun[2]=display2;printf("1.创建子进程\n2.不创建子进程\n请输入您的选择:");scanf("%d",&select);if(select==1) /*如果用户输入1,创建进程*/{result=fork(); /*调用fork函数创建进程,返回值存在变量result中*/if(result==-1){perror("创建进程出错");exit(1);}}if (result==0) /*子进程*/{printf("这是子进程(进程号:%d,父进程号:%d): ",getpid(),getppid());printf("进入思科(Cisco)1912交换机开机界面。
\n ");printf("1 user(s) now active on Management Console.\n");printf("\tUser Interface Menu\n");printf("\t[0] Menus\n");printf("\t[1] Command Line\n");printf("\t[2] IP Configuration\n");printf("Enter Selection:");scanf("%d",&num); /*运用函数指针,运行相应的子程序*/if(num>=0&&num<=2)(*fun[num])();exit(0);}else{waitpid(result,&status,0); /*父进程调用waitpid函数,消除僵尸进程*/printf("这是父进程(进程号:%d,父进程号:%d)\n ",getpid(),getppid());if(WIFEXITED(status)==0)printf("子进程非正常终止,子进程终止状态:%d\n", WIFEXITED(status));elseprintf("子进程正常终止,子进程终止状态:%d\n", WIFEXITED(status));exit(0);}}/*子程序部分*/void display0(){printf("您选择进入了菜单模式\n");}void display1(){printf("您选择进入了命令行模式\n");}void display2(){printf("您选择进入了IP地址配置模式\n");}【步骤1】:设计编辑源程序代码[root@localhost root]#vim 6-8.c【步骤2】:用gcc编译程序[root@localhost root]#gcc 6-8.c –o 6-8【步骤3】:运行程序[root@localhost root]#./6-81.创建子进程2.不创建子进程请输入您的选择:2这是父进程(进程号:5028,父进程号:4739)子进程非正常终止,子进程终止状态:0@再次运行程序[root@localhost root]#./6-81.创建子进程2.不创建子进程请输入您的选择:1这是子进程(进程号:5044,父进程号:5043): 进入思科(Cisco)1912交换机开机界面。