#include <stdio.h> #include <sys/types.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <error.h> #include <wait.h> #include <unistd.h> int main( ){ int pid1,pid2,pid3; int fd[2]; char outpipe[60],inpipe[60]; pipe(fd);//创建一个管道 while ((pid1=fork( ))==-1); printf("pid1=%d\n",pid1); if(pid1==0){ printf("The Child process 1 is sending message!\n"); lockf(fd[1],1,0);//互斥 sprintf(outpipe,"This is the child 1 process's message!\n"); write(fd[1],outpipe,60); sleep(1);//自我阻塞1秒,让出机会执行下一个进程,增加并发度 lockf(fd[1],0,0); exit(0); } else{ while((pid2=fork( ))==-1); printf("pid2=%d\n",pid2); if(pid2==0){ printf("The Child process 2 is sending message!\n"); lockf(fd[1],1,0); sprintf(outpipe,"This is the child 2 process's message!\n"); write(fd[1],outpipe,60); sleep(1); lockf(fd[1],0,0); exit(0); } else{ while((pid3=fork( ))==-1); printf("pid3=%d\n",pid3); if(pid3==0){ printf("The Child process 3 is sending message!\n"); lockf(fd[1],1,0); sprintf(outpipe,"This is the child 3 process's message!\n"); write(fd[1],outpipe,60); sleep(1); lockf(fd[1],0,0); exit(0); } else{ wait(0);//同步 read(fd[0],inpipe,60); printf("\n%s",inpipe); wait(0); read(fd[0],inpipe,60); printf("%s\n",inpipe); wait(0); read(fd[0],inpipe,60); printf("%s\n",inpipe); exit(0); } } } return 0; }(1)
时间: 2024-02-15 10:28:40 浏览: 32
这段代码是一个使用管道实现进程间通信的示例程序。它创建了三个子进程,每个子进程向管道中写入自己的消息,父进程从管道中读取这些消息并打印出来。
具体来说,首先通过 `pipe(fd)` 创建了一个管道,然后通过三次 `fork()` 分别创建了三个子进程。每个子进程都先使用 `lockf()` 函数对管道进行互斥,然后向管道中写入自己的消息,并使用 `sleep()` 函数自我阻塞 1 秒,让出机会执行下一个进程,从而增加并发度。最后再使用 `lockf()` 函数解除互斥并退出进程。
父进程则通过三次 `wait()` 函数等待子进程退出,并使用 `read()` 函数从管道中读取子进程写入的消息,并打印出来。
注意,这段代码中使用了固定的消息长度 60,这可能会导致消息被截断或者浪费空间。在实际使用中,可以通过动态分配内存来解决这个问题。
相关问题
#include <stdio.h> #include <sys/types.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <error.h> #include <wait.h> #include <unistd.h> int main( ){ int pid1,pid2,pid3; int fd[2]; char outpipe[60],inpipe[60]; pipe(fd);//创建一个管道 while ((pid1=fork( ))==-1); printf("pid1=%d\n",pid1); if(pid1==0){ printf("The Child process 1 is sending message!\n"); lockf(fd[1],1,0);//互斥 sprintf(outpipe,"This is the child 1 process's message!\n"); write(fd[1],outpipe,60); sleep(1);//自我阻塞1秒,让出机会执行下一个进程,增加并发度 lockf(fd[1],0,0); exit(0); } else{ while((pid2=fork( ))==-1); printf("pid2=%d\n",pid2); if(pid2==0){ printf("The Child process 2 is sending message!\n"); lockf(fd[1],1,0); sprintf(outpipe,"This is the child 2 process's message!\n"); write(fd[1],outpipe,60); sleep(1); lockf(fd[1],0,0); exit(0); } else{ while((pid3=fork( ))==-1); printf("pid3=%d\n",pid3); if(pid3==0){ printf("The Child process 3 is sending message!\n"); lockf(fd[1],1,0); sprintf(outpipe,"This is the child 3 process's message!\n"); write(fd[1],outpipe,60); sleep(1); lockf(fd[1],0,0); exit(0); } else{ wait(0);//同步 read(fd[0],inpipe,60); printf("\n%s",inpipe); wait(0); read(fd[0],inpipe,60); printf("%s\n",inpipe); wait(0); read(fd[0],inpipe,60); printf("%s\n",inpipe); exit(0); } } } return 0; }(1)(1)指出父进程与三个子进程并发执行的顺序,并说明原因。(2)说明是如何实现父子进程之间的同步的(3)源代码中,如果父进程执行读消息四次什么结果?(4)修改代码,父进程发送消息,三个子进程分别读。
(1) 父进程与三个子进程的并发执行顺序是不确定的,取决于操作系统的调度算法和进程的执行速度。在这段代码中,通过自我阻塞 1 秒和使用 `lockf()` 函数对管道进行互斥的方式,增加了子进程之间的并发度,从而使它们更有可能在父进程执行之前完成。但是,具体的执行顺序是不可预测的。
(2) 父进程与子进程之间的同步是通过 `wait()` 函数实现的。在父进程中调用 `wait()` 函数可以等待子进程退出,并获取子进程的退出状态。在这段代码中,父进程调用了三次 `wait()` 函数,分别等待三个子进程退出。
(3) 如果父进程执行读消息四次,那么它会从管道中读取三条消息和一条空消息。因为管道是一个先进先出的队列,如果管道中没有消息,那么 `read()` 函数会立即返回,并且不会阻塞进程。
(4) 修改代码,父进程发送消息,三个子进程分别读的示例代码如下:
```c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <error.h>
#include <wait.h>
#include <unistd.h>
int main( ){
int pid1, pid2, pid3;
int fd[2];
char outpipe[60], inpipe[60];
pipe(fd);//创建一个管道
while ((pid1=fork( ))==-1);
printf("pid1=%d\n",pid1);
if(pid1==0){
exit(0);
} else{
while((pid2=fork( ))==-1);
printf("pid2=%d\n",pid2);
if(pid2==0){
exit(0);
} else{
while((pid3=fork( ))==-1);
printf("pid3=%d\n",pid3);
if(pid3==0){
exit(0);
} else{
// 父进程发送消息
printf("The parent process is sending message!\n");
sprintf(outpipe, "This is the parent process's message!\n");
write(fd[1], outpipe, 60);
sleep(1);
// 子进程分别读取消息
read(fd[0], inpipe, 60);
printf("Child process 1: %s", inpipe);
read(fd[0], inpipe, 60);
printf("Child process 2: %s", inpipe);
read(fd[0], inpipe, 60);
printf("Child process 3: %s", inpipe);
exit(0);
}
}
}
return 0;
}
```
在这个示例中,父进程先向管道中写入一条消息,然后三个子进程分别从管道中读取这条消息,并打印出来。
为程序添加备注注意对齐#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
/*
* 该函数实现了类似于Linux终端中的ls -l命令的功能,可以显示文件的详细信息。
* 参数file为要显示信息的文件名;
* 参数st为文件的stat结构体,包含了文件的各种信息,如权限、大小、修改时间等。
*/
#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 limit[10]="rwxrwxrwx"; // 文件权限对应的字符
char perms[11]="----------"; // 文件权限字符串
int i=0;
int j=0;
int k=0;
struct passwd *user; // 用户信息结构体
struct group *group; // 用户组信息结构体
// 设置文件权限字符串
for(i=0;i<9;i++) {
if(st.st_mode & (1<<(8-i))) {
perms[i]=limit[i];
}
}
// 根据文件类型设置第一个字符
switch(st.st_mode & S_IFMT) {
case S_IFLNK:
perms[0]='l';
break;
case S_IFDIR:
perms[0]='d';
break;
case S_IFCHR:
perms[0]='c';
break;
case S_IFBLK:
perms[0]='b';
break;
case S_IFIFO:
perms[0]='p';
break;
case S_IFSOCK:
perms[0]='s';
break;
default:
perms[0]='-';
break;
}
printf("%s ",perms); // 输出文件权限
printf("%d ",(int)st.st_nlink); // 输出硬链接数
user=getpwuid(st.st_uid); // 获取文件拥有者信息
group=getgrgid(st.st_gid); // 获取文件拥有者组信息
printf("%s %s ",user->pw_name,group->gr_name); // 输出拥有者和所属组
printf("%8ld ",st.st_size); // 输出文件大小
char *time_str=ctime(&st.st_mtime); // 获取文件最后修改时间
time_str[strlen(time_str)-1]='\0'; // 去掉不需要的换行符
printf("%s ",time_str); // 输出最后修改时间
printf("%s\n",file); // 输出文件名
}
阅读全文