一個想法是模仿標準的Unix工具tee
的功能,而是完全在您的程序中完成,而不依賴外部重定向。
所以我寫了一個簡單的函數,mytee()
,這似乎工作。它採用shmget(), pipe(), fork(), and dup2()
:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
static char *mytee(int size) {
int shmid = shmget(IPC_PRIVATE, size + 1, 0660 | IPC_CREAT);
int pipe_fds[2];
pipe(pipe_fds);
switch (fork()) {
case -1: // = error
perror("fork");
exit(EXIT_FAILURE);
case 0: { // = child
char *out = shmat(shmid, 0, 0), c;
int i = 0;
out[0] = 0;
dup2(pipe_fds[0], 0); // redirect pipe to child's stdin
setvbuf(stdout, 0, _IONBF, 0);
while (read(0, &c, 1) == 1 && i < size) {
printf("<%c>", c); // pass parent's stdout to real stdout,
out[i++] = c; // and then buffer in mycapture buffer
out[i] = 0; // (the extra <> are just for clarity)
}
_exit(EXIT_SUCCESS);
}
default: // = parent
dup2(pipe_fds[1], 1); // replace stdout with output to child
setvbuf(stdout, 0, _IONBF, 0);
return shmat(shmid, 0, 0); // return the child's capture buffer
}
}
我的測試程序是:
int main(void) {
char *mycapture = mytee(100); // capture first 100 bytes
printf("Hello World"); // sample test string
sleep(1);
fprintf(stderr, "\nCaptured: <%s>\n", mycapture);
return 0;
}
輸出是:
<H><e><l><l><o>< ><W><o><r><l><d>
Captured: <Hello World>
要在應用程序中使用此,在mytee()
你會需要用替換測試語句。您可能需要處理read
的呼叫中的信號。而每兩個dup2()
的之後,你可能需要添加:
close(pipe_fds[0]);
close(pipe_fds[1]);
有關這種東西的參考,例如見的優秀和短27歲的220頁奧賴利book在Dave Curry的Unix系統上使用C.
好吧,我已經在python中完成了它,但是我需要將它重新集成到ANSI C中。因此除了調用另一個進程之外沒有其他辦法嗎?我不知道,我是否在某處違反堆棧高度。 – Stasik
限制你使用C的是什麼?更簡潔的方法是通過過濾器來管理程序的輸出,而不是執行所需的更改(假定命令行使用,操作系統支持管道等)。 – Throwback1986
約束是微控制器上現有的構建和發佈系統+運行時 – Stasik