#include "sys/types.h" #include "sys/file.h" #include "unistd.h" char r_buf[4]; char w_buf[4]; int pipe_fd[2]; pid_t pid1, pid2, pid3, pid4; int producer(int id); int consumer(int id); int main(int argc,char **argv) { if(pipe(pipe_fd)<0) { printf("pipe create error \n"); exit(-1); } else { printf("pipe is created successfully!\n"); if((pid1=fork())==0) producer(1); if((pid2=fork())==0) producer(2); if((pid3=fork())==0) consumer(1); if((pid4=fork())==0) consumer(2); } close(pipe_fd[0]); close(pipe_fd[1]); int i,pid,status; for(i=0;i<4;i++) pid=wait(&status); exit(0); } int producer(int id) { printf("producer %d is running!\n",id); close(pipe_fd[0]); int i=0; for(i=1;i<10;i++) { sleep(3); if(id==1) strcpy(w_buf,"aaa\0"); else strcpy(w_buf,"bbb\0"); if(write(pipe_fd[1],w_buf,4)==-1) printf("write to pipe error\n"); } close(pipe_fd[1]); printf("producer %d is over!\n",id); exit(id); } int consumer(int id) { close(pipe_fd[1]); printf("producer %d is running!\n",id); if (id==1) strcpy(w_buf,"ccc\0"); else strcpy(w_buf,"ddd\0"); while(1) { sleep(1); strcpy(r_buf,"eee\0"); if(read(pipe_fd[0],r_buf,4)==0) break; printf("consumer %d get %s, while the w_buf is %s\n",id,r_buf,w_buf); } close(pipe_fd[0]); printf("consumer %d is over!\n", id); exit(id); }
时间: 2024-04-27 15:20:57 浏览: 16
这是一个使用管道实现生产者-消费者模型的 C 语言程序。其中,使用了 fork() 函数创建了四个子进程,分别作为两个生产者和两个消费者。通过管道实现了生产者向消费者传递数据的功能。
具体来说,程序中有两个缓存区 r_buf 和 w_buf,分别用于存储从管道中读取的数据和向管道中写入的数据。使用 pipe() 函数创建了一个管道,使用 fork() 函数创建了四个子进程。其中,pid1 和 pid2 分别代表两个生产者,pid3 和 pid4 分别代表两个消费者。
生产者的代码逻辑如下:
1. 关闭管道的读端,只保留写端。
2. 在一个循环中,每隔三秒向管道中写入一个字符串。
3. 写入完毕后关闭管道的写端,退出进程。
消费者的代码逻辑如下:
1. 关闭管道的写端,只保留读端。
2. 在一个循环中,每隔一秒从管道中读取一个字符串,并打印出来。
3. 读取完毕后关闭管道的读端,退出进程。
在主函数中,等待四个子进程全部结束后退出程序。
相关问题
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <pwd.h> #include <grp.h> #include <time.h> void shell_ls_l(char *file,struct stat st) { char limi
ted[11]; // 文件权限 mode_t mode = st.st_mode; limitted[0] = (S_ISDIR(mode)) ? "d" : "-"; limitted[1] = (mode & S_IRUSR) ? "r" : "-"; limitted[2] = (mode & S_IWUSR) ? "w" : "-"; limitted[3] = (mode & S_IXUSR) ? "x" : "-"; limitted[4] = (mode & S_IRGRP) ? "r" : "-"; limitted[5] = (mode & S_IWGRP) ? "w" : "-"; limitted[6] = (mode & S_IXGRP) ? "x" : "-"; limitted[7] = (mode & S_IROTH) ? "r" : "-"; limitted[8] = (mode & S_IWOTH) ? "w" : "-"; limitted[9] = (mode & S_IXOTH) ? "x" : "-"; limitted[10] = '\0'; printf("%s ", limitted); // 链接数、所有者、所在组、文件大小、创建时间、文件名 printf("%ld ", (long)st.st_nlink); printf("%s ", getpwuid(st.st_uid)->pw_name); printf("%s ", getgrgid(st.st_gid)->gr_name); printf("%lld ", (long long)st.st_size); char time_buf[20]; strftime(time_buf, 20, "%b %d %H:%M", localtime(&st.st_ctime)); printf("%s ", time_buf); printf("%s\n", file); } int main(int argc, char *argv[]) { DIR *dir; struct dirent *ptr; struct stat st; char path[256]; if (argc == 1) { getcwd(path, 256); dir = opendir(path); while ((ptr = readdir(dir)) != NULL) { if (ptr->d_name[0] == '.') continue; stat(ptr->d_name, &st); shell_ls_l(ptr->d_name, st); } } else if (argc == 2) { if (strcmp(argv[1], "-l") == 0) { getcwd(path, 256); dir = opendir(path); while ((ptr = readdir(dir)) != NULL) { if (ptr->d_name[0] == '.') continue; stat(ptr->d_name, &st); shell_ls_l(ptr->d_name, st); } } else { dir = opendir(argv[1]); while ((ptr = readdir(dir)) != NULL) { if (ptr->d_name[0] == '.') continue; sprintf(path, "%s/%s", argv[1], ptr->d_name); stat(path, &st); shell_ls_l(ptr->d_name, st); } } } else if (argc == 3) { if (strcmp(argv[1], "-l") == 0) { dir = opendir(argv[2]); while ((ptr = readdir(dir)) != NULL) { if (ptr->d_name[0] == '.') continue; sprintf(path, "%s/%s", argv[2], ptr->d_name); stat(path, &st); shell_ls_l(ptr->d_name, st); } } } return 0; }
这是一个简单的实现Linux命令ls -l的程序,可以列出文件的权限、链接数、所有者、所在组、文件大小、创建时间、文件名等信息。
基于以下代码,分析_exit()与exit()在进程退出时的不同行为,结合行缓冲机制,如果调用_exit()函数结束进程并打印父进程信息,应该怎样操作:#include <stdio.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> int global=22; char buf[]="the test content!\n"; int mai
n() {
int var=88;
pid_t pid;
int fd;
if ((fd=open("testfile",O_CREAT|O_WRONLY|O_TRUNC,0644)) <0) {
perror("open error");
exit(1);
}
if (write(fd,buf,sizeof(buf)-1) != sizeof(buf)-1) {
perror("write error");
exit(1);
}
printf("before fork\n");
if ((pid=fork())<0) {
perror("fork error");
exit(1);
} else if (pid==0) {
global++;
var++;
printf("child changed\n");
printf("global=%d, var=%d\n",global,var);
// exit(0);
_exit(0);
}
if (waitpid(pid,NULL,0)<0) {
perror("waitpid error");
exit(1);
}
printf("parent changed\n");
printf("global=%d, var=%d\n",global,var);
exit(0);
}
1. _exit()与exit()的区别在于_exit()是直接终止进程,而exit()则是先执行一些清理工作(如调用函数库中的清理函数),然后再终止进程。
2. 在本代码中,如果使用_exit()函数结束进程并打印父进程信息,应该在子进程中添加以下代码:
```
printf("parent process id=%d\n", getppid());
_exit(0);
```
这样子进程就会直接终止,同时打印出父进程的进程ID。如果使用exit()函数,则需要在子进程中添加清理函数并调用exit()函数来结束进程。