计算机操作系统实验二进程管理
实验目标
1、掌握getpid和getppid函数的使用
2、掌握fork函数的使用
3、理解exec函数族6个函数的区别,掌握6个函数的使用
4、理解exit和_exit的区别,掌握exit的使用
5、理解wait和waitpid的区别,掌握wait和waitpid的使用
实验内容
- 分别用execlp()、execl()和execv()函数实现命令“find / -name abc”的功能,将代码和执行结果粘贴到实验报告中。
- 编写多进程程序,掌握fork()、exec()、wait()和waitpid()等函数的使用,进一步理解在Linux中多进程编程的步骤,要求:
程序有3 个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls -l”指令,另一个子进程在暂停5s 之后异常退出,父进程先用阻塞方式等待第一个子进程的结束,然后用非阻塞方式等待另一个子进程的退出,待收集到第二个子进程结束的信息,父进程就返回;
实验步骤
1.分别用execlp()、execl()和execv()函数实现命令“find / -name abc”的功能,将代码和执行结果粘贴到实验报告中。
exec 函数族可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新的进程替换了
在进程中使用exec函数族的作用是使运行结果替换原有进程,所以为了避免父进程被替换掉,需要先在父进程中通过fork()函数创建子进程,然后在子进程中使用exec函数。在shell命令行执行ps命令,实际上是shell进程调用fork复制一个新的子进程,再利用exec系统调用将新产生的子进程完全替换成ps进程
- execlp函数
【函数语法】
execlp(file,arg1,arg2,……,NULL)
execlp()会从PATH 环境变量(可通过env命令查看$PATH)所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束。
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(){
if (fork() == 0){
if (execlp("find", "find", "/", "-name", "abc", "NULL") < 0){
perror("Excelp error\n");
}
}
}
- execl函数
【函数语法】
execl()无法从PATH 环境变量所指的目录中查找符合参数file的文件名执行该文件。所以需要使用完整的文件目录来查找对应的可执行文件。注意目录必须以“/”开头,否则将被视为文件名
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(){
if (fork() == 0){
if (execl("/bin/find", "find", "/", "-name", "abc", "NULL") < 0){
perror("Execl error\n");
}
}
}
- execv函数
【函数语法】
通过构造指针数组的方式来传递参数,参数列表一定要以NULL 作为结尾标识符,execv()使用系统默认环境变量,不需要传递新环境变量。
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(){
char *arg[] = {"find", "/", "-name", "abc", "NULL"}
if (fork() == 0){
if (execv("/bin/find", arg) < 0)){
perror("Execv error\n");
}
}
}
2.编写多进程程序,掌握fork()、exec()、wait()和waitpid()等函数的使用,进一步理解在Linux中多进程编程的步骤,要求:
程序有3 个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls -l”指令,另一个子进程在暂停5s 之后异常退出,父进程先用阻塞方式等待第一个子进程的结束,然后用非阻塞方式等待另一个子进程的退出,待收集到第二个子进程结束的信息,父进程就返回;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
pid_t pid1, pid2;
int status1, status2;
// 创建第一个子进程
pid1 = fork();
if (pid1 == -1) {
perror("Error");
exit(1);
}
if (pid1 == 0) { // 子进程1
execlp("ls", "ls", "-l", NULL);
perror("Exec failed");
exit(1);
} else { // 父进程
// 阻塞等待第一个子进程结束
wait(&status1);
// 创建第二个子进程
pid2 = fork();
if (pid2 == -1) {
perror("Error");
exit(1);
}
if (pid2 == 0) { // 子进程2
sleep(5); // 暂停5秒
exit(2);
} else { // 父进程
// 非阻塞等待第二个子进程结束
waitpid(pid2, &status2, WNOHANG);
if (WIFEXITED(status2)) {
printf("第二个子进程已结束,退出状态: %d\n", WEXITSTATUS(status2));
}
}
}
return 0;
}