linux实验7

实验七 Linux进程控制实验

学号:6130116217

专业班级:计算机科学与技术165班

课程名称:Linux程序设计实验

一、实验项目名称

Linux进程控制实验

二、实验目的

通过编写多进程程序和守护进程,熟练掌握fork()、exec()、wait()和waitpid()等函数的使用方法和守护进程的编写方法,并进一步理解在Linux中多进程编程方法。

三、实验基本原理

Linux进程控制

四、主要仪器设备及耗材

硬件: PC机;
软件:Windows OS,VMware,Fedora10.0或其他Linux发行版。

五、实验步骤

1. 编写c程序,要求程序运行时共有3个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls -l”指令,另一个子进程在暂停5s之后退出,父进程先用阻塞方式等待第一个子进程的结束,然后用非阻塞方式等待另一个子进程的退出,待收集到第二个子进程结束的信息,父进程就结束。

请问如下代码是否能实现上述要求,若不能请指出原因并对代码进行修改。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void) {
	pid_t child1, child2, child;
	/*创建两个子进程*/
	child1 = fork();
	child2 = fork();
	/*子进程1的出错处理*/
	if (child1 == -1) {
		printf("Child1 fork error\n");
		exit(1);
	} else if (child1 == 0) { /*在子进程1中调用execlp()函数*/
		printf("In child1: execute 'ls -l'\n");
		if (execlp("ls", "ls","-l", NULL)<0) {
			printf("Child1 execlp error\n");
		}
	}

	if (child2 == -1) { /*子进程2的出错处理*/
		printf("Child2 fork error\n");
		exit(1);
	} else if( child2 == 0 ) { /*在子进程2中使其暂停5s*/
		printf("In child2: sleep for 5 seconds and then exit\n");
		sleep(5);
		exit(0);
	} else { /*在父进程中等待两个子进程的退出*/
		printf("In father process:\n");
		child = waitpid(child1, NULL, 0); /* 阻塞式等待 */
		if (child == child1) {
			printf("Get child1 exit code\n");
		} else {
			printf("Error occured!\n");
		}

		do {
			child =waitpid(child2, NULL, WNOHANG);/* 非阻塞式等待 */
			if (child == 0) {
				printf("The child2 process has not exited!\n");
				sleep(1);
			}
		} while (child == 0);

		if (child == child2) {
			printf("Get child2 exit code\n");
		} else {
			printf("Error occured!\n");
		}
	}
	exit(0);
}

在这里插入图片描述
答:不能实现要求,当执行代码child1 = fork() 时,child1 = 0,当执行代码child2 = fork()时,将复制父进程的内存(此时父进程中child1 =0,即父进程为child1进程),所以在child2所代表进程中child1 = 0,将执行ls -l 命令。所有代码将执行两次ls -l命令。
修改后代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <syspes.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void) {
	pid_t child1, child2, child;
	/*创建两个子进程*/
	child1 = fork();
	if (child1 == -1) {
		printf("Child1 fork error\n");
		exit(1);
	} else if (child1 == 0) { /*在子进程1中调用execlp()函数*/
		printf("In child1: execute 'ls -l'\n");
		if (execlp("ls", "ls","-l", NULL)<0) {
			printf("Child1 execlp error\n");
		}
	} else {
		child2=fork();
		if (child2 == -1) { /*子进程2的出错处理*/
			printf("Child2 fork error\n");
			exit(1);
		} else if( child2 == 0 ) { /*在子进程2中使其暂停5s*/
			printf("In child2: sleep for 5 seconds and then exit\n");
			sleep(5);
			exit(0);
		} else { /*在父进程中等待两个子进程的退出*/
			printf("In father process:\n");
			child = waitpid(child1, NULL, 0); /* 阻塞式等待 */
			if (child == child1) {
				printf("Get child1 exit code\n");
			} else {
				printf("Error occured!\n");
			}

			do {
				child =waitpid(child2, NULL, WNOHANG);/* 非阻塞式等待 */
				if (child == 0) {
					printf("The child2 process has not exited!\n");
					sleep(1);
				}
			} while (child == 0);

			if (child == child2) {
				printf("Get child2 exit code\n");
			} else {
				printf("Error occured!\n");
			}
		}
	}
}

运行结果:
在这里插入图片描述

2. 调试教材例6.7、6.10程序
①例6.7
/*6-7.c 程序:通过宏WIFEXITED(stat_val),取得子进程exit(3)返回的结束代码*/
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
        pid_t pid;
        pid = fork();
        if (pid < 0) {
                perror("fork failed");
                exit(1);
        }
        if (pid == 0) {
                int i;
                for (i = 3; i > 0; i--) {
                        printf("This is the child\n");
                        sleep(1);
                }
                exit(3);
        } else {
                int stat_val;
                waitpid(pid, &stat_val, 0);
                if (WIFEXITED(stat_val))
                        printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
                else if (WIFSIGNALED(stat_val))
                        printf("Child terminated abnormally, signal %d\n",
                               WTERMSIG(stat_val));
        }
        return 0;
}

编译运行
在这里插入图片描述

②例6.10
/*6-10.c 程序:守护进程和它的子进程退出信息写入系统日志文件*/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<syslog.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/stat.h>
int main() {
	pid_t child1,child2;
	int i;
	child1=fork();
	if(child1>0) /*(1)创建子进程,终止父进程*/
		exit(0); /*这是第一子进程,后台继续执行*/
	else if(child1< 0) {
		perror("创建子进程失败"); /*fork 失败,退出*/
		exit(1);
	}
	setsid(); /*(2)在子进程中创建新会话*/
	chdir("/"); /*(3)改变工作目录到“/”*/
	umask(0); /*(4)重设文件创建掩码*/
	for(i=0; i< NOFILE; ++i) /*(5)关闭文件描述符*/
		close(i);
	openlog("例6-10 程序信息",LOG_PID,LOG_DAEMON);/* 调用openlog 函数打开日志文件
*/
	child2=fork();
	if(child2==-1) {
		perror("创建子进程失败"); /*fork 失败,退出*/
		exit(1);
	} else if(child2==0) {
		syslog(LOG_INFO,"第二子进程暂停5 秒!"); /* 调用syslog,写入系统日志*/
		sleep(5); /*睡眠5 秒钟*/
		syslog(LOG_INFO,"第二子进程结束运行。");/* 调用syslog,写入系统日志*/
		exit(0);
	} else { /* 返回值大于0 代表父进程,这是第二子进程的父进程,即第一子进程*/
		waitpid(child2,NULL,0); /*第一子进程调用waitpid 函数,等待第二子进程*/
		syslog(LOG_INFO, "第一子进程在等待第二子进程结束后,也结束运行。");
		closelog(); /*调用closelog,关闭日志服务*/
		while(1) { /*无限循环*/
			sleep(10); /*睡眠10 秒钟*/
		}
	}
}

编译运行
在这里插入图片描述
等待一段时间,查看/var/log/messages文件最后三行
在这里插入图片描述

六、实验数据及处理结果

七、思考讨论题

(1)如何用ps命令查看某个进程是否为守护进程?
答:执行代码ps -aux 可以查看守护进程
(2)如何结束一个守护进程?
答:ps -aux 查看守护进程pid
结束守护进程:kill -9 pid

八、参考资料

1.金国庆等,Linux程序设计(第二版),浙江大学出版社,2014年4月
2. Neil Matthew,《Linux程序设计》(第4版), 人民邮电出版社,2014年9月
3. 杨宗德,《Linux高级程序设计》(第三版),人民邮电出版社,2012年11月
4. Daniel P.,《深入理解Linux内核》(第三版),中国电力出版社,2013年1月

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值