上学期接触了linux系统,刚好操作系统课程的实验内容也都是要求在linux下完成,几个实验中个人认为对两个进程通信实验了解学习的比较好,所以这一篇和下一篇记录一下两个实验过程中的学习收获和实验成果。
实验要求:由父进程创建一个管道和三个子进程,实现子进程和父进程间的通信(三个子进程发送后父进程接收)并测试管道大小以及进程对管道的实际写入字节数。
#include
#include
#include
#include
#include
#include
#define MAX_DATA_LEN 256
#define DELAY_TIME 1
int main()
{
pid_t pid1,pid2,pid3;
int pipe_fd[2];
int len,realen,pipeid;
char buf[MAX_DATA_LEN],outpipe[MAX_DATA_LEN];
pipeid=pipe(pipe_fd);
if(pipeid<0)
{
printf("pipe error\n");
exit(1);
}
if((pid1=fork())==-1){
printf("pid1 error!\n");
exit(1);
}
if(pid1==0) {
sleep(DELAY_TIME);
printf("pid1 is:%d\n",getpid());
close(pipe_fd[0]);
sprintf(outpipe,"I'm child1!\n");
len=strlen(outpipe);
realen=write(pipe_fd[1], outpipe, len);
printf("child1 writes %d bytes\n",realen);
exit(0);
}
if((pid2=fork())==-1){
printf("pid2 error!\n");
exit(1);
}
if(pid2==0) {
sleep(DELAY_TIME);
printf("pid2 is:%d\n",getpid());
close(pipe_fd[0]);
sprintf(outpipe,"I'm child2!\n");
len=strlen(outpipe);
realen=write(pipe_fd[1], outpipe, len);
printf("child2 writes %d bytes\n",realen);
exit(0);
}
if((pid3=fork())==-1){
printf("pid3 error!\n");
exit(1);
}
if(pid3==0) {
sleep(DELAY_TIME);
printf("pid3 is:%d\n",getpid());
close(pipe_fd[0]);
sprintf(outpipe,"I'm child3!\n");
len=strlen(outpipe);
realen=write(pipe_fd[1], outpipe, len);
printf("child3 writes %d bytes\n",realen);
exit(0);
}
else{
sleep(DELAY_TIME*3);
pid1 = waitpid(pid1,NULL,WUNTRACED);
pid2 = waitpid(pid2,NULL,WUNTRACED);
pid3 = waitpid(pid3,NULL,WUNTRACED);
printf("father pid is:%d\n",getpid());
close(pipe_fd[1]);
read(pipe_fd[0],buf,sizeof(buf));
printf("children date is: \n%s\n",buf);
}
return 0;
}
由于fork()创建的几个进程之间运行的先后顺序无法确定,所以这个实验中存在同步互斥问题,父进程需要等待三个子进程运行完毕后再读出并打印管道中的数据。不过我没有用信号量,而是使用了waitpid()实现的。
测试管道容量的实现比较简单,设置了一个固定大小为1024的数据段,只需要把这一段重复写入管道,每写入一次都计数一次,写到管道满时即可通过写入次数来得知管道的大小了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_DATA_LEN 1024
void write_to_pipe(int pipe_fd[2]);
int main(void)
{
int pipe_fd[2];
pid_t pid;
int ret = -1;
pipe(pipe_fd);
pid = fork();
if(pid == 0) {
write_to_pipe(pipe_fd);
}
else {
wait(NULL);
}
}
void write_to_pipe(int pipe_fd[2])
{
int count, ret;
char buf[MAX_DATA_LEN];
close(pipe_fd[0]);
memset(buf, '*', MAX_DATA_LEN);
ret = write(pipe_fd[1], buf, sizeof(buf));
count = 1;
printf(" Pipe has: %d kb\n", count);
while (1) {
ret = write(pipe_fd[1], buf, sizeof(buf));
if(ret == -1){
printf("1\n");
break;
}
count++;
printf(" Pipe has: %d kb\n", count);
}
}
实验心得:熟悉了管道通信的基础框架,对fork、vfork也有了更深入的了解。