- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我刚开始做这些事情,我正在尝试做这个练习,但我显然做错了一些事情,但我不知道是什么。
编写一个 C 程序,以 4 个文件名作为参数。该程序必须创建 3 个子进程。每个 child 将从他的文件中读取三个字符,并通过 PIPE 将它们传达给他的父亲。父亲会检查读取的字符,如果3个 child 收到的3个字符的序列相同,则将其打印在第四个文件中。一旦其中一个子进程完成读取其文件,所有其他子进程也必须结束。
我的代码:
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/wait.h>
#include <signal.h>
void primoFiglio(char *file,int pipe[]);
void secondoFiglio(char *file ,int pipe[]);
void terzoFiglio(char *file ,int pipe[]);
void main(int argc,char **argv){
pid_t pid;
pid_t processi[3];
int pipe1[2],pipe2[2],pipe3[2],n1,n2,n3;
int status;
int fd;
char buffer1[10],buffer2[10],buffer3[10];
if(argc!=5){
printf("Numero errato di parametri, riprovare.\n");
exit(1);
}
else{
if(pipe(pipe1)<0||pipe(pipe2)<0||pipe(pipe3)<0){
perror("Pipe error");
exit(1);
}
else{
if((pid=fork())<0){
perror("Fork");
exit(1);
}
else{
if(pid==0){
close(pipe1[0]);
primoFiglio(argv[1],pipe1);
}
else{
processi[0]=pid;
if((pid=fork())<0){
perror("Fork");
exit(1);
}
else{
if(pid==0){
close(pipe2[0]);
secondoFiglio(argv[2],pipe2);
}
else{
processi[1]=pid;
if((pid=fork())<0){
perror("Fork");
exit(1);
}
else{
if(pid==0){
close(pipe3[0]);
terzoFiglio(argv[3],pipe3);
}
else{
processi[2]=pid;
fd=open(argv[4],O_RDWR|O_APPEND|O_CREAT,0666);
if(fd<0){
perror("File");
exit(1);
}
else{
close(pipe1[1]);
close(pipe2[1]);
close(pipe3[1]);
while((n1=read(pipe1[0],buffer1,3)>0)&&(n2=read(pipe2[0],buffer2,3)>0)&&(n3=read(pipe3[0],buffer3,3)>0)){
if(n1==3&&n2==3&&n3==3){
printf("%c %c %c\n",buffer1[0],buffer2[0],buffer3[0]);
if(buffer1[0]==buffer2[0]&&buffer2[0]==buffer3[0]){
if(buffer1[1]==buffer2[1]&&buffer2[1]==buffer3[1]){
if(buffer1[2]==buffer2[2]&&buffer2[2]==buffer3[2]){
write(fd,buffer1,n1);
}
}
}
}
}
close(pipe1[0]);
close(pipe2[0]);
close(pipe3[0]);
close(fd);
if(wait(&status)!=-1){
if(status>>8==2){
kill(processi[1],SIGKILL);
kill(processi[2],SIGKILL);
}
else if(status>>8==3){
kill(processi[0],SIGKILL);
kill(processi[2],SIGKILL);
}
else if(status>>8==4){
kill(processi[0],SIGKILL);
kill(processi[1],SIGKILL);
}
exit(0);
}
}
}
}
}
}
}
}
}
}
}
void primoFiglio(char *file ,int pipe[]){
int fd,nread;
char buffer[10];
fd=open(file,O_RDONLY);
if(fd<0){
perror("File");
exit(1);
}
else{
while((nread=read(fd,buffer,3))>0){
if(nread==3){
write(pipe[1],buffer,nread);
}
}
close(fd);
printf("Primo figlio term\n");
exit(2);
}
}
void secondoFiglio(char *file ,int pipe[]){
int fd,nread;
char buffer[10];
fd=open(file,O_RDONLY);
if(fd<0){
perror("File");
exit(1);
}
else{
while((nread=read(fd,buffer,3))>0){
if(nread==3){
write(pipe[1],buffer,nread);
}
}
close(fd);
printf("Secondo figlio term\n");
exit(3);
}
}
void terzoFiglio(char *file ,int pipe[]){
int fd,nread;
char buffer[10];
fd=open(file,O_RDONLY);
if(fd<0){
perror("File");
exit(1);
}
else{
while((nread=read(fd,buffer,3))>0){
if(nread==3){
write(pipe[1],buffer,nread);
}
}
close(fd);
printf("Terzo figlio term\n");
exit(4);
}
}
Father 无法从每个管道(只能读取一个)读取 3 个字符,因此它不会将任何内容写入第四个文件。有小费吗?
编辑谢谢您的回答对我帮助很大我尝试改进我的代码,现在它可以工作了你觉得怎么样?
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
void child(char *file,int pipe[]);
int main(int argc,char **argv){
pid_t pid;
pid_t process[3];
int pipe1[2],pipe2[2],pipe3[2],n1,n2,n3;
int status;
int fd;
char buffer1[10],buffer2[10],buffer3[10];
if(argc!=5){
printf("Wrong number of parameters\n");
exit(1);
}
else if(pipe(pipe1)<0||pipe(pipe2)<0||pipe(pipe3)<0){
perror("Pipe error");
exit(1);
}
else if((pid=fork())<0){
perror("Fork");
exit(1);
}
else if(pid==0){
child(argv[1],pipe1);
}
else{
process[0]=pid;
if((pid=fork())<0){
perror("Fork");
exit(1);
}
else if(pid==0){
close(pipe1[0]);
close(pipe1[1]);
child(argv[2],pipe2);
}
else{
process[1]=pid;
if((pid=fork())<0){
perror("Fork");
exit(1);
}
else if(pid==0){
close(pipe2[0]);
close(pipe2[1]);
child(argv[3],pipe3);
}
else{
process[2]=pid;
fd=open(argv[4],O_RDWR|O_APPEND|O_CREAT,0666);
if(fd<0){
perror("File");
exit(1);
}
close(pipe1[1]);
close(pipe2[1]);
close(pipe3[1]);
while((n1=read(pipe1[0],buffer1,3))>2&&(n2=read(pipe2[0],buffer2,3))>2&&(n3=read(pipe3[0],buffer3,3))>2){
printf("Reading...\n");
if(memcmp(buffer1,buffer2,3)==0&&memcmp(buffer2,buffer3,3)==0)
write(fd,buffer1,n1);
pid=waitpid(0,&status,WNOHANG);
if(pid==process[0]){
kill(process[1],SIGKILL);
kill(process[2],SIGKILL);
}
else if(pid==process[1]){
kill(process[0],SIGKILL);
kill(process[2],SIGKILL);
}
else if(pid==process[2]){
kill(process[0],SIGKILL);
kill(process[1],SIGKILL);
}
}
close(pipe1[0]);
close(pipe2[0]);
close(pipe3[0]);
close(fd);
exit(0);
}
}
}
}
void child(char *file ,int pipe[]){
int fd,nread;
char buffer[10];
fd=open(file,O_RDONLY);
if(fd<0){
perror("File");
exit(1);
}
while((nread=read(fd,buffer,3))>0){
if(nread==3){
write(pipe[1],buffer,nread);
}
}
close(fd);
exit(0);
}
最佳答案
除了各种评论之外,我注意到三个“figlio”函数彼此非常相似。它们也没有显式关闭足够的管道文件描述符。每个子进程都可以访问来自三个管道的所有 6 个文件描述符,并且理论上应该关闭除它们将用于写入的一个文件描述符之外的所有文件描述符。我创建了一个figlioGenerale()
函数传递 3 对文件描述符并关闭除其中之一的写入端之外的所有文件描述符。它还获取一个标记字符串来标识它代表哪个子级,以及它应该使用的退出状态。 else
为父级完成工作的 block 也可以明智地制作成一个函数。
请注意,我在 fork()
中使用了多重赋值行:
else if ((pid = process[0] = fork()) < 0)
else if ((pid = process[1] = fork()) < 0)
else if ((pid = process[2] = fork()) < 0)
这使得没有必要添加缩进级别来对 process
进行赋值。数组(原版中的 processi
)。事实上,分配给pid
如果使用后续测试 process[N]
则可以避免而不是pid
(对于 N
的适当值 - 0
、 1
或 2
)。
我不喜欢使用SIGKILL;最好使用 SIGTERM 或 SIGHUP 来请求进程退出。实际上没有必要检查哪个进程终止了;向三个 child 中的每一个发送终止信号就足够了。我使用标准错误作为错误消息。我还安排 children 忽略SIGPIPE。这迫使write()
返回错误,该错误被发现并中断了写入循环。
还可以进行其他更改 - 其中一些已在评论中概述。
所有这些都会导致这样的代码:
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static void figlioGenerale(char *file, int estatus, const char *figlio,
int p_use[], int p_spare1[], int p_spare2[]);
int main(int argc, char **argv)
{
pid_t pid;
pid_t process[3];
int pipe1[2], pipe2[2], pipe3[2], n1, n2, n3;
int status;
int fd;
char buffer1[10], buffer2[10], buffer3[10];
if (argc != 5)
{
printf("Numero errato di parametri, riprovare.\n");
fprintf(stderr, "Usage: %s infile1 infile2 infile3 outfile\n", argv[0]);
exit(1);
}
else if (pipe(pipe1) < 0 || pipe(pipe2) < 0 || pipe(pipe3) < 0)
{
perror("Pipe error");
exit(1);
}
else if ((pid = process[0] = fork()) < 0)
{
perror("Fork");
exit(1);
}
else if (pid == 0)
{
figlioGenerale(argv[1], 2, "Primo", pipe1, pipe2, pipe3);
}
else if ((pid = process[1] = fork()) < 0)
{
perror("Fork");
exit(1);
}
else if (pid == 0)
{
figlioGenerale(argv[2], 3, "Secondo", pipe2, pipe1, pipe3);
}
else if ((pid = process[2] = fork()) < 0)
{
perror("Fork");
exit(1);
}
else if (pid == 0)
{
figlioGenerale(argv[3], 4, "Terzo", pipe3, pipe1, pipe2);
}
else
{
fd = open(argv[4], O_RDWR | O_TRUNC | O_CREAT, 0666);
if (fd < 0)
{
perror("File");
exit(1);
}
else
{
close(pipe1[1]);
close(pipe2[1]);
close(pipe3[1]);
while ((n1 = read(pipe1[0], buffer1, 3) == 3) &&
(n2 = read(pipe2[0], buffer2, 3) == 3) &&
(n3 = read(pipe3[0], buffer3, 3) == 3))
{
if (memcmp(buffer1, buffer2, 3) == 0 &&
memcmp(buffer1, buffer3, 3) == 0)
{
write(fd, buffer1, 3);
}
}
close(pipe1[0]); /* Children will get SIGPIPE when writing */
close(pipe2[0]);
close(pipe3[0]);
close(fd);
kill(process[0], SIGTERM);
kill(process[1], SIGTERM);
kill(process[2], SIGTERM);
while ((pid = wait(&status)) != -1)
printf("PID %d exited with status 0x%.4X\n", pid, status);
}
}
return 0;
}
static void figlioGenerale(char *file, int estatus, const char *figlio,
int p_use[], int p_spare1[], int p_spare2[])
{
int fd, nread;
char buffer[3];
fd = open(file, O_RDONLY);
signal(SIGPIPE, SIG_IGN); /* Causes write() to return with error on EOF */
/* Close unused ends of pipes */
close(p_use[0]);
close(p_spare1[0]);
close(p_spare1[1]);
close(p_spare2[0]);
close(p_spare2[1]);
if (fd < 0)
{
fprintf(stderr, "file %s: %s\n", file, strerror(errno));
exit(1);
}
else
{
while ((nread = read(fd, buffer, 3)) > 0)
{
if (nread == 3)
{
if (write(p_use[1], buffer, nread) != nread)
break;
}
}
close(fd);
close(p_use[1]);
printf("%s figlio term\n", figlio);
exit(estatus);
}
}
运行时(从 pipe89
编译的程序 pipe89.c
),我得到如下输出:
$ (
> set -x
> rmk -u pipe89
> pipe89 pipe89.c pipe89.c pipe89.c pipe.output
> diff pipe89.c pipe.output
> ls -ld pipe89*
> pipe89 pipe89.c pipe89.c /dev/null pipe.output
> ls -dl pipe89*
> pipe89 pipe89.c pipe89.c /dev/null pipe.output
> pipe89 pipe89.c pipe89.c /dev/null pipe.output
> pipe89 pipe89.c pipe89.c /dev/null pipe.output
> )
+++ rmk -u pipe89
gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pipe89.c -o pipe89 -L./lib -lsoq
+++ pipe89 pipe89.c pipe89.c pipe89.c pipe.output
Primo figlio term
Terzo figlio term
Secondo figlio term
PID 24675 exited with status 0x0400
PID 24674 exited with status 0x0300
PID 24673 exited with status 0x0200
+++ diff pipe89.c pipe.output
+++ ls -ld pipe89 pipe89.c pipe89.dSYM pipe89.sh
-rwxr-xr-x 1 jleffler staff 13704 Jan 18 14:25 pipe89
-rw-r--r-- 1 jleffler staff 3444 Jan 18 14:11 pipe89.c
drwxr-xr-x 3 jleffler staff 96 Jan 18 13:45 pipe89.dSYM
-rw-r--r-- 1 jleffler staff 315 Jan 18 14:24 pipe89.sh
+++ pipe89 pipe89.c pipe89.c /dev/null pipe.output
Terzo figlio term
Secondo figlio term
PID 24681 exited with status 0x000F
PID 24680 exited with status 0x000F
PID 24679 exited with status 0x000F
+++ ls -dl pipe89 pipe89.c pipe89.dSYM pipe89.sh
-rwxr-xr-x 1 jleffler staff 13704 Jan 18 14:25 pipe89
-rw-r--r-- 1 jleffler staff 3444 Jan 18 14:11 pipe89.c
drwxr-xr-x 3 jleffler staff 96 Jan 18 13:45 pipe89.dSYM
-rw-r--r-- 1 jleffler staff 315 Jan 18 14:24 pipe89.sh
+++ pipe89 pipe89.c pipe89.c /dev/null pipe.output
Terzo figlio term
PID 24685 exited with status 0x000F
PID 24686 exited with status 0x000F
PID 24684 exited with status 0x000F
+++ pipe89 pipe89.c pipe89.c /dev/null pipe.output
Terzo figlio term
PID 24689 exited with status 0x000F
PID 24690 exited with status 0x000F
PID 24688 exited with status 0x000F
+++ pipe89 pipe89.c pipe89.c /dev/null pipe.output
Terzo figlio term
Secondo figlio term
PID 24694 exited with status 0x000F
PID 24693 exited with status 0x000F
PID 24692 exited with status 0x000F
$ rmk pipe89 && pipe89 pipe89.c pipe89.c /dev/null pipe.output
'pipe89' is up to date.
Terzo figlio term
PID 24699 exited with status 0x0400
PID 24698 exited with status 0x000F
PID 24697 exited with status 0x000F
$ rmk pipe89 && pipe89 pipe89.c /dev/null pipe89.c pipe.output
'pipe89' is up to date.
Secondo figlio term
PID 24708 exited with status 0x0300
PID 24709 exited with status 0x000F
PID 24707 exited with status 0x000F
$ rmk pipe89 && pipe89 /dev/null pipe89.c pipe89.c pipe.output
'pipe89' is up to date.
Primo figlio term
PID 24713 exited with status 0x0200
PID 24714 exited with status 0x000F
PID 24715 exited with status 0x000F
$
由于某种原因,当程序从子 shell 运行时,所有进程都会被 SIGTERM 信号 ( 0x000F
) 终止,但是当直接从命令行运行时,其中一个进程(读取的进程) /dev/null
) 以其自己的退出状态退出。我必须将其归因于进程调度的怪癖。
如果管道是在单个文件描述符数组中创建的,并且子进程被告知要从哪个管道描述符中读取,可能会更好。子进程可能会将其复制到文件描述符 1(标准输出 - dup2(pipes[out], STDOUT_FILENO)
),然后简单地关闭传递给它的所有 6 个描述符。
int pipes[6];
if (pipe(&pipes[0]) < 0 ||
pipe(&pipes[2]) < 0 ||
pipe(&pipes[4]) < 0)
…
figlioGenerale(argv[1], 2, "Primo", 1, pipes);
figlioGenerale(argv[2], 3, "Secondo", 3, pipes);
figlioGenerale(argv[3], 4, "Terzo", 5, pipes);
关于带 fork 和管道的 C 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59803965/
有3个 repo : 有 OpenAI Baselines 存储库:https://github.com/openai/baselines . 我有它的 fork :https://github.co
我试图了解在调用 fork() 后复制文件描述符的含义及其对争用的可能影响。 在“Linux 编程接口(interface)”24.2.1 (p517) 中: When a fork() is per
我对 systemd 如何跟踪主进程存在后仍然存在的主进程的子进程感兴趣? 最佳答案 Systemd 为此使用了 cgroups。在启动任何使用服务文件定义的可执行文件之前,systemd 会创建一个
这是输出--- 家长:我的pid是4525 parent :我 parent 的 pid 是 3350 parent 开始- 4525 3350 fork 前 fork 前 child 4526 45
我之前 fork 了 jockm/vert.x 并向他发送了拉取请求。现在我想 fork vert-x/vert.x (jockm/vert.x 的上游)并向他们发送不同的拉取请求。但是,当我单击“F
我想控制从 Perl 脚本派生的进程的名称 a。理想情况下它会像这样: ./forker.pl | ... | | fork("forked.pl"); |\ | \ | `--------\ |
我知道 fork() 在更高级别上做什么。我想知道的是这个—— 一旦有 fork 调用,trap 指令就会跟随并且控制跳转以执行 fork “处理程序”。现在,这个创建子进程的处理程序如何通过创建另一
我正在研究操作系统测验,但我不知道输出什么 if(fork()) fork() 会产生。有人可以解释吗? 我不明白这一行: if(fork()) 编辑: 我所说的“输出”是指如果执行此代码,将
这个问题在这里已经有了答案: Why does this program print "forked!" 4 times? (6 个答案) 关闭 3 年前。 在 C 中,fork() 函数将为父进程
有什么方法可以区分程序中不同 fork() 函数创建的子进程。 global variable i; SIGCHLD handler function() { i--; } handle() {
我正在重新开发一个系统,该系统将通过 http 向多个供应商之一发送消息。原来是perl脚本,重新开发很可能也会用perl。 在旧系统中,同时运行多个 perl 脚本,每个供应商运行 5 个。当一条消
Git 的新手,仍然有点困惑。我在 github 上 fork 了一个项目,想将项目所有者最近对原始项目所做的一些更改引入/merge 到我的 fork 中。这可能吗?该项目是只读的,但基本上,我想让
根据维基百科(可能是错误的) When a fork() system call is issued, a copy of all the pages corresponding to the par
我需要帮助了解如何在 Go 中妖魔化进程。 package main import ( "fmt" "os" ) func start() { var procAttr os.Pro
我已经执行了这段代码。我知道消息的顺序是任意顺序的(因为我明确没有使用信号量)我的程序流程如何?为什么? 父级被执行,因此“baz”被打印一次。有人可以解释为什么不打印“bar”吗?为什么我得到“fo
这个问题已经有答案了: Why does this program print "forked!" 4 times? (6 个回答) 已关闭 5 年前。 我对 fork 进程有疑问。我有一个代码是 i
我在弄清楚如何使用在不同进程之间创建的列表时遇到了麻烦。我所拥有的是: FileList.h - 我创建的列表 #include "Node.h" typedef struct FileList {
好吧,所以我一直在 stackoverflow 上查找这个问题,并且肯定在谷歌上搜索了半个小时,但我得到的答案似乎与我真正想做的事情几乎没有任何关系,希望有人能提供帮助我在这方面,代码如下: int
我正在尝试了解 fork-join 的工作原理。 维基百科有以下合并排序示例,其中左半部分被 fork ,右半部分由当前线程处理。 mergesort(A, lo, hi): if lo t
下面的代码输出了一系列的过程,它到底做了什么: _PARENT_ / \ /
我是一名优秀的程序员,十分优秀!