请注意:1.采用的是希冀平台下的linux虚拟机。
2.所用教材是《Linux高级程序设计》,刘加海、季江民编著,浙江大学出版社,2022年8月第1版。《Linux程序设计》(第4版),[英]Neil Matthew等著;陈健、宋健建译,人民邮电出版社,2010年6月。
第六次实验课主要内容 :目录文件读取、进程控制
实验1 文件的读写操作与目录文件
1.实验目的
巩固文件的读写方法,熟悉目录文件的打开及读取方法
2.实验任务与要求
编写程序,将当前目录下的文件夹dir1下的所有普通文件依次拷贝至当前目录下的文件夹dir2中,且保持文件名不变。要求:不考虑递归情形,不能使用system函数或exec系列函数。
3. 编写程序
给出实现该任务的源代码、运行结果的截图,并写出实验体会(可选)。
(1)运行结果截图:
(2)源代码:
include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
void copy_file(const char *src,const char *des){
int fdsrc,fddes,nbytes;
char buf[20];
fdsrc=open(src,O_RDONLY);
if(fdsrc<0){
perror("error opening source file");
return;
}
fddes=open(des,O_CREAT | O_TRUNC | O_WRONLY,0644);
if(fddes<0){
perror("error opening the target file");
close(fdsrc);
return;
}
while((nbytes = read(fdsrc,buf,20))>0){
if(write(fddes,buf,nbytes)<0){
perror("error writing target file");
break;
}
}
close(fdsrc);
close(fddes);
}
int main(){
DIR *dir;
struct dirent *ptr;
char src[50],des[50];
dir = opendir("./dir1");
if(dir==NULL)
{
perror("error opening dir1 directory");
return 1;
}
while((ptr = readdir(dir)) !=NULL)
{
if(ptr->d_type==DT_REG)
{
strcpy(src,"./dir1/");
strcat(src,ptr->d_name);
strcpy(des,"./dir2/");
strcat(des,ptr->d_name);
copy_file(src,des);
}
}
closedir(dir);
return 0;
}
实验2 教材思考题遴选(第6章)
- 实验目的
掌握进程的并发执行、僵尸进程的产生和避免。
- 实验任务与要求
请按照如下要求设计程序,完成如下思考题(教材第6章P235页,原思考题中说法不准确的地方已经进行了修正)。
思考题:程序设计要体现子进程与父进程并发执行的效果(即父子进程交替执行各自的printf语句),并且子进程退出后父进程才退出;还应该避免子进程变为僵尸进程。参考代码如下所示。
pid=fork();
if(pid==0){
for(i=0; i<10; i++){
printf("This is the child process, pid: %d\n", getpid());
sleep(1);
}
exit(0);
}
else if(pid>0){
for(i=0; i<5; i++){
printf("This is the parent process, pid: %d\n", getpid());
sleep(5);
}
}
提示:建议通过增加子进程执行循环的时长来避免子进程成为僵尸进程。
现有的参考代码中,父进程的循环耗时长(共约25秒),子进程的循环耗时短(共约10秒),假设wait或waitpid函数在父进程的for循环体之后,则在wait或waitpid函数发挥作用前的一小段时间内,子进程可能已经变为僵尸进程,设计程序时应避免这种情况。
3. 编写程序
给出实现该任务的源代码、运行结果的截图,并写出实验体会(可选)。
运行结果的截图:
实现的源代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
int main()
{
pid_t pid;
int i;
sem_t sem;
sem_init(&sem, 0, 1);
pid = fork();
if (pid == 0)
{
for (i = 0; i < 10; i++)
{
sem_wait(&sem);
printf("This is the child process, pid: %d\n", getpid());
sem_post(&sem);
sleep(1);
}
exit(0);
}
else if (pid > 0)
{
for (i = 0; i < 5; i++)
{
sem_wait(&sem);
printf("This is the parent process, pid: %d\n", getpid());
sem_post(&sem);
sleep(5);
}
waitpid(pid, NULL, 0);
}
sem_destroy(&sem);
return 0;
}
实验3 子进程的创建
- 实验目的
掌握子进程的创建方法、父子进程的并发执行以及wait函数的使用
- 实验任务与要求
在父子进程中分别执行不同的任务,例如在子进程中执行文件编辑任务(可以利用system函数执行gedit命令),在父进程中执行网络连通情况的测试任务(可以利用system函数执行ping命令,用法见下),子进程退出后父进程才退出。
提示:
(1)文本编辑命令gedit的执行时间是从启动文本编辑窗口开始算,直至关闭该窗口
(2)网络连通测试命令ping的IP地址可以是本机IP(请使用ifconfig查看,例如IP地址为100.64.0.2)或某个网址(例如www.baidu.com)。
ping -c 20 100.64.0.2 #表示ping本机IP地址20次。
若网络连通测试功能不可用,则可以改成其它的操作,例如循环输出若干行字符。
(3)程序执行的关键步骤如下:子进程执行gedit命令,弹出文本编辑窗口,用户可随意输入一些内容;此过程中,父进程并发执行ping命令,进行20次网络连通测试之后,输出一条提示语句“已ping20次,完成测试任务!”;父进程继而执行wait或waitpid函数,等待子进程的结束,即等待用户关闭gedit命令所产生的文本编辑窗口;子进程正常结束后,父进程利用WIFEXITED、WEXITSTATUS一对宏,捕获子进程的退出码并输出。
可参考如下运行结果,完成程序:
关闭文本编辑窗口后,出现如下运行结果:
3. 编写程序
给出实现该任务的源代码、运行结果的截图,并写出实验体会(可选)。
运行结果的截图:
源代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(){
pid_t pid;
pid = fork();
if(pid<0){
printf("error ocurred!\n");
}else if(pid==0){
system("gedit &");
exit(1);
}else{
system("ping -c 20 100.64.0.2");
printf("The task has been pinged for 20 times.\n");
int status;
waitpid(pid,&status,0);
if(WIFEXITED(status)){
printf("The PID of the child process is:%d,the exit code is:%d\n",pid,WEXITSTATUS(status));
}
else{
printf("The child process exception");
}
}
return 0;
}