1.编写多进程程序,该实验有3个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls -l”指令,另一个子进程在暂停5s之后异常退出,父进程先用阻塞方式等待第一个子进程的结束,然后用非阻塞方式等待另一个子进程的退出,等待收集到第二个子进程结束的信息,父进程就返回。实验流程图如图4.1所示。
lab431.c源码:
//此处命名为lab431.c
/* multi_proc_wrong.c */
#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);
}
/* 在子进程1中调用execlp()函数 */
else if (child1 == 0)
{
printf("In child1: execute 'ls -l'\n");
if (execlp("ls", "ls", "-l", NULL) < 0)
{
printf("Child1 execlp error\n");
}
}
/* 子进程2的出错处理 */
if (child2 == -1)
{
printf("Child2 fork error\n");
exit(1);
}
/* 在子进程2中使其暂停5s */
else if( child2 == 0 )
{
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);
}
lab432.c源码:
/* multi_proc.c */
#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();
/* 子进程1的出错处理 */
if (child1 == -1)
{
printf("Child1 fork error\n");
exit(1);
}
/* 在子进程1中调用execlp()函数 */
else if (child1 == 0)
{
printf("In child1: execute 'ls -l'\n");
if (execlp("ls", "ls", "-l", NULL) < 0)
{
printf("Child1 execlp error\n");
}
}
/* 在父进程中再创建进程2,然后等待两个子进程的退出 */
else
{
child2 = fork();
/* 子进程2的出错处理 */
if (child2 == -1)
{
printf("Child2 fork error\n");
exit(1);
}
/* 在子进程2中使其暂停5s */
else if(child2 == 0)
{
printf("In child2: sleep for 5 seconds and then exit\n");
sleep(5);
exit(0);
}
//hcy1031
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);
}
}
2.编写有名管道多路通信程序,实验流程图如图4.2所示。
lab4_4.c源码:
/* pipe_select.c */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#define FIFO1 "in1"
#define FIFO2 "in2"
#define MAX_BUFFER_SIZE 1024 /* 缓冲区大小 */
#define IN_FILES 3 /* 多路复用输入文件数目 */
#define TIME_DELAY 60 /* 超时值秒数 */
#define MAX(a, b) ((a > b)?(a):(b))
int main(void)
{
int fds[IN_FILES];
char buf[MAX_BUFFER_SIZE];
int i, res, real_read, maxfd;
struct timeval tv;
fd_set inset,tmp_inset;
fds[0] = 0;
/* 创建两个有名管道 */
if (access(FIFO1, F_OK) == -1)
{
if ((mkfifo(FIFO1, 0666) < 0) && (errno != EEXIST))
{
printf("Cannot create fifo file\n");
exit(1);
}
}
if (access(FIFO2, F_OK) == -1)
{
if ((mkfifo(FIFO2, 0666) < 0) && (errno != EEXIST))
{
printf("Cannot create fifo file\n");
exit(1);
}
}
/* 以只读非阻塞方式打开两个管道文件 */
if((fds[1] = open (FIFO1, O_RDONLY|O_NONBLOCK)) < 0)
{
printf("Open in1 error\n");
return 1;
}
if((fds[2] = open (FIFO2, O_RDONLY|O_NONBLOCK)) < 0)
{
printf("Open in2 error\n");
return 1;
}
/* 取出两个文件描述符中的较大者 */
maxfd = MAX(MAX(fds[0], fds[1]), fds[2]);
/* 初始化读集inset,并在读文件描述符集中加入相应的描述集 */
FD_ZERO(&inset);
for (i = 0; i < IN_FILES; i++)
{
FD_SET(fds[i], &inset);
}
FD_SET(0, &inset);
tv.tv_sec = TIME_DELAY;
tv.tv_usec = 0;
// 循环测试该文件描述符是否准备就绪,并调用select()函数对相关文件描述符做相应操作
while(FD_ISSET(fds[0],&inset) || FD_ISSET(fds[1],&inset) || FD_ISSET(fds[2],
&inset))
{
/* 文件描述符集的备份,以免每次都进行初始化 */
tmp_inset = inset;
res = select(maxfd + 1, &tmp_inset, NULL, NULL, &tv);
switch(res)
{
case -1:
{
printf("Select error\n");
return 1;
}
break;
case 0: /* Timeout */
{
printf("Time out\n");
return 1;
}
break;
default:
{
for (i = 0; i < IN_FILES; i++)
{
if (FD_ISSET(fds[i], &tmp_inset))
{
memset(buf, 0, MAX_BUFFER_SIZE);
real_read = read(fds[i], buf, MAX_BUFFER_SIZE);
if (real_read < 0)
{
if (errno != EAGAIN)
{
return 1;
}
}
else if (!real_read)
{
close(fds[i]);
FD_CLR(fds[i], &inset);
}
else
{
if (i == 0)
{ /* 主程序终端控制 */
if ((buf[0] == 'q') || (buf[0] == 'Q'))
{
return 1;
}
}
else
{ /* 显示管道输入字符串 */
buf[real_read] = '\0';
printf("%s", buf);
}
}
} /* end of if */
} /* end of for */
}
break;
} /* end of switch */
} /* end of while */
return 0;
}
通过本次实验了解主机与开发板的连接和通信(包括串口和网络连接、主机与开发板之间的文件传输);掌握如何编写和编译Linux应用程序,并下载到开发板运行;通过编写多进程程序,熟练掌握fork()、exec()、wait()和waitpid()等函数的使用;通过编写有名管道多路通信实验,进一步掌握管道的创建、读写等操作。