我正在撰寫一個程式,其中父行程需要能夠與另一個子行程通信,所以我撰寫了一個函式,將子行程的標準輸出和輸入重定向到管道。
int create_child_piped_io(int* pipe_in, int* pipe_out, const char* program, char* argv[], char* envp[])
{
int stdin_pipe[2];
int stdout_pipe[2];
int child;
if(pipe(stdin_pipe) < 0)
{
return -1;
}
if(pipe(stdout_pipe) < 0)
{
close(stdin_pipe[0]);
close(stdin_pipe[1]);
}
child = fork();
if(child == 0)
{
close(stdin_pipe[1]);
close(stdout_pipe[0]);
if(dup2(stdin_pipe[0], STDIN_FILENO) < 0)
{
close(stdin_pipe[0]);
close(stdout_pipe[1]);
exit(errno);
}
if(dup2(stdout_pipe[1], STDOUT_FILENO) < 0)
{
close(stdin_pipe[0]);
close(stdout_pipe[1]);
exit(errno);
}
close(stdin_pipe[0]);
close(stdout_pipe[1]);
execve(program, argv, envp);
exit(1);
}
else if(child > 0)
{
close(stdin_pipe[0]);
close(stdout_pipe[1]);
*pipe_in = stdin_pipe[1];
*pipe_out = stdout_pipe[0];
return child;
}
else
{
close(stdin_pipe[0]);
close(stdin_pipe[1]);
close(stdout_pipe[0]);
close(stdout_pipe[1]);
exit(errno);
}
return child;
}
int main()
{
int input, output;
char* argv[] = {"program"};
char* envp[] = {NULL};
int cpid = create_child_piped_io(&input, &output, "/home/jaden/dev/c /pipes/program", argv, envp);
char c;
while(read(output, &c, 1) == 1)
{
printf("%c", c);
}
printf("done\n");
int status;
waitpid(cpid, &status, 0);
close(input);
close(output);
}
這作業正常,但我注意到當從子行程寫入標準輸出時,它不會立即發送到管道。這是子行程將運行的程式。
int main()
{
// i < 1025 gets sent to pipe after sleep(10)
// i > 1025 send first 1024 bytes to pipe immediately
for(int i = 0; i < 1024; i )
{
write(1, "a", 1);
}
sleep(10);
return 0;
}
輸出只會在子行程結束后發送到管道。我嘗試發送不同數量的資料。事實證明,每次我向標準輸出寫入超過 1024 時,它都會被發送到管道。這讓我相信它正在被緩沖。我不明白為什么會這樣,因為管道也是記憶體中的緩沖區,所以它只是緩沖緩沖區。如果這是標準行為,是否有任何方法可以將其關閉,因為我想在寫入資料后立即獲取資料。
我正在使用 linux mint 20.3。
uj5u.com熱心網友回復:
你的問題在這里:
while(read(output, &c, 1) == 1)
{
printf("%c", c);
}
當您使用系統呼叫閱讀時,您正在使用printf()
連接到終端通過 glibc stdio 進行寫入。輸出是Line-Buffered。如果您更改代碼以使用系統呼叫撰寫,例如
while(read(output, &c, 1) == 1)
{
write (1, &c, 1);
}
神秘的緩沖消失了。
正如@ShadowRanger指出的那樣,如果您需要stdio.h
函式提供的格式,那么您可以使用將連接到終端時setvbuf()
的正常行緩沖更改為無緩沖。stdout
例如,setvbuf(stdout, NULL, _IONBF, 0);
這將使通過printf()
等的輸出能夠以無緩沖的方式使用。見man 3 setbuf
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/469129.html