通过管道传递字符时出现奇怪的字母
Strange letter when passing character through a pipe
我有一个内容为 abcefghz
的输入文件。我想使用管道,以便子进程 p1 每次向其父进程发送 1 个字母,父进程将使用 ASCII 代码+1 转换此字符串(abcefghz
将变为 cdfghi{
)。这个新字符串将通过另一个管道发送到另一个子进程,该子进程将在输出文件上打印结果。
这是代码:
int main (int argc, char **argv)
{
pid_t pid1, pid2;
int inputFile, outputFile;
char stringaDalFile[256];
char successivo;
char stringaRisultato[256];
int fd1[2], fd2[2]; // Pipe
inputFile = open(argv[1], O_RDONLY);
outputFile = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
pipe(fd1);
pipe(fd2);
pid1 = fork();
if (pid1 == 0) {
while ( (nread=read(inputFile, stringaDalFile, 1)) > 0) {
close(fd1[0]);
write(fd1[1], stringaDalFile, 1);
}
close(inputFile);
}
else {
close(fd1[1]);
while ( read(fd1[0], stringaDalFile, 1) > 0 ) {
successivo = converti(stringaDalFile[0]);
write(fd2[1], &successivo, 1);
}
}
pid2 = fork();
if (pid2 == 0) {
close(fd2[1]);
if (read(fd2[0], stringaRisultato, 1) == -1) {
perror("Errore");
exit(1);
}
else {
while ( read(fd2[0], stringaRisultato, 1) > 0 ) {
write(STDOUT_FILENO, stringaRisultato, strlen(stringaRisultato)); //dbg
write(outputFile, stringaRisultato, strlen(stringaRisultato));
}
}
close(outputFile);
exit(0);
}
return 0;
}
char converti (char carattere)
{
return carattere+1;
}
不幸的是,这似乎无法 100% 工作,字符串已转换但程序进入似乎无限循环:
如果我CTRL-C
和gedit file2.txt
,这是它的内容:
.
我该如何解决这个问题?
read
returns 读取的字节数,因此您应该使用它来将 NUL 终止字符添加到它填充的字符串中,如下所示
while ( (bytesread = read(inputFile, stringaDalFile, 1)) > 0) {
stringaDalFile[bytesread] = '[=10=]';
....
您的代码中存在一些问题:
真正的问题,这里:
write(outputFile, stringaRisultato, strlen(stringaRisultato));
当 stringaRisultato
开头只有一个有效字符而后面没有 NUL-terminator 时,您正在使用 strlen(stringaRisultato)
。只需使用 1
即可。
您一次只读一个字符,不需要 256 个字符的字符串。将 stringaDalFile
和 stringaRisultato
更改为两个单独的 char
变量:carattereDalFile
和 carattereRisultante
.
在第一个 child(在 if (pid1 == 0)
内)中,您正在循环执行 close(fd1[0])
。您应该将其移出 while
.
同样在第一个 child 中,你没有做 exit(0)
。这就是导致您的程序保持 运行.
的原因
这一行里面第二个child:
if (read(fd2[0], stringaRisultato, 1) == -1) {
仅在您想跳过第一个字符时才有用。这是故意的吗?如果不是,请删除 if
并仅使用 while (read(...) > 0)
.
在开始第二个 child(将从中读取)之前,您正在将所有内容写入管道 fd2[1]
。如果输入文件太大(一些 KB),这将导致管道内部缓冲区被填满,并会在下一个 write()
尝试执行时阻塞您的程序,使其永远不会结束。要解决此问题,您应该同时启动两个 child 进程。这将需要更改代码的结构和逻辑,但这是可行的。
因为我认为这不是这里的真正问题,而且这个程序很可能是出于教育目的而编写的,所以我将把它留给你并解决以上其余问题。
工作代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
char converti (char carattere);
int main (int argc, char **argv)
{
pid_t pid1, pid2;
int inputFile, outputFile;
char carattereDalFile, carattereRisultante, successivo; // renamed
int fd1[2], fd2[2];
inputFile = open(argv[1], O_RDONLY);
outputFile = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
pipe(fd1);
pipe(fd2);
pid1 = fork();
if (pid1 == 0) {
close(fd1[0]); // <== moved out of the while loop
while (read(inputFile, &carattereDalFile, 1) > 0) {
write(fd1[1], &carattereDalFile, 1);
}
close(inputFile);
exit(0); // <== added
} else {
close(fd1[1]);
while (read(fd1[0], &carattereDalFile, 1) > 0) {
successivo = converti(carattereDalFile);
write(fd2[1], &successivo, 1);
}
}
pid2 = fork();
if (pid2 == 0) {
close(fd2[1]);
if (read(fd2[0], &carattereRisultante, 1) == -1) {
perror("Errore");
exit(1);
} else {
while (read(fd2[0], &carattereRisultante, 1) > 0) {
write(outputFile, &carattereRisultante, 1);
}
}
close(outputFile);
exit(0);
}
return 0;
}
char converti (char carattere)
{
return carattere+1;
}
我有一个内容为 abcefghz
的输入文件。我想使用管道,以便子进程 p1 每次向其父进程发送 1 个字母,父进程将使用 ASCII 代码+1 转换此字符串(abcefghz
将变为 cdfghi{
)。这个新字符串将通过另一个管道发送到另一个子进程,该子进程将在输出文件上打印结果。
这是代码:
int main (int argc, char **argv)
{
pid_t pid1, pid2;
int inputFile, outputFile;
char stringaDalFile[256];
char successivo;
char stringaRisultato[256];
int fd1[2], fd2[2]; // Pipe
inputFile = open(argv[1], O_RDONLY);
outputFile = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
pipe(fd1);
pipe(fd2);
pid1 = fork();
if (pid1 == 0) {
while ( (nread=read(inputFile, stringaDalFile, 1)) > 0) {
close(fd1[0]);
write(fd1[1], stringaDalFile, 1);
}
close(inputFile);
}
else {
close(fd1[1]);
while ( read(fd1[0], stringaDalFile, 1) > 0 ) {
successivo = converti(stringaDalFile[0]);
write(fd2[1], &successivo, 1);
}
}
pid2 = fork();
if (pid2 == 0) {
close(fd2[1]);
if (read(fd2[0], stringaRisultato, 1) == -1) {
perror("Errore");
exit(1);
}
else {
while ( read(fd2[0], stringaRisultato, 1) > 0 ) {
write(STDOUT_FILENO, stringaRisultato, strlen(stringaRisultato)); //dbg
write(outputFile, stringaRisultato, strlen(stringaRisultato));
}
}
close(outputFile);
exit(0);
}
return 0;
}
char converti (char carattere)
{
return carattere+1;
}
不幸的是,这似乎无法 100% 工作,字符串已转换但程序进入似乎无限循环:
如果我CTRL-C
和gedit file2.txt
,这是它的内容:
我该如何解决这个问题?
read
returns 读取的字节数,因此您应该使用它来将 NUL 终止字符添加到它填充的字符串中,如下所示
while ( (bytesread = read(inputFile, stringaDalFile, 1)) > 0) {
stringaDalFile[bytesread] = '[=10=]';
....
您的代码中存在一些问题:
真正的问题,这里:
write(outputFile, stringaRisultato, strlen(stringaRisultato));
当
stringaRisultato
开头只有一个有效字符而后面没有 NUL-terminator 时,您正在使用strlen(stringaRisultato)
。只需使用1
即可。您一次只读一个字符,不需要 256 个字符的字符串。将
stringaDalFile
和stringaRisultato
更改为两个单独的char
变量:carattereDalFile
和carattereRisultante
.在第一个 child(在
if (pid1 == 0)
内)中,您正在循环执行close(fd1[0])
。您应该将其移出while
.同样在第一个 child 中,你没有做
exit(0)
。这就是导致您的程序保持 运行. 的原因
这一行里面第二个child:
if (read(fd2[0], stringaRisultato, 1) == -1) {
仅在您想跳过第一个字符时才有用。这是故意的吗?如果不是,请删除
if
并仅使用while (read(...) > 0)
.在开始第二个 child(将从中读取)之前,您正在将所有内容写入管道
fd2[1]
。如果输入文件太大(一些 KB),这将导致管道内部缓冲区被填满,并会在下一个write()
尝试执行时阻塞您的程序,使其永远不会结束。要解决此问题,您应该同时启动两个 child 进程。这将需要更改代码的结构和逻辑,但这是可行的。因为我认为这不是这里的真正问题,而且这个程序很可能是出于教育目的而编写的,所以我将把它留给你并解决以上其余问题。
工作代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
char converti (char carattere);
int main (int argc, char **argv)
{
pid_t pid1, pid2;
int inputFile, outputFile;
char carattereDalFile, carattereRisultante, successivo; // renamed
int fd1[2], fd2[2];
inputFile = open(argv[1], O_RDONLY);
outputFile = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
pipe(fd1);
pipe(fd2);
pid1 = fork();
if (pid1 == 0) {
close(fd1[0]); // <== moved out of the while loop
while (read(inputFile, &carattereDalFile, 1) > 0) {
write(fd1[1], &carattereDalFile, 1);
}
close(inputFile);
exit(0); // <== added
} else {
close(fd1[1]);
while (read(fd1[0], &carattereDalFile, 1) > 0) {
successivo = converti(carattereDalFile);
write(fd2[1], &successivo, 1);
}
}
pid2 = fork();
if (pid2 == 0) {
close(fd2[1]);
if (read(fd2[0], &carattereRisultante, 1) == -1) {
perror("Errore");
exit(1);
} else {
while (read(fd2[0], &carattereRisultante, 1) > 0) {
write(outputFile, &carattereRisultante, 1);
}
}
close(outputFile);
exit(0);
}
return 0;
}
char converti (char carattere)
{
return carattere+1;
}