![在 C 程序中创建的 Bash 中使用命名管道](https://linux22.com/image/6648/%E5%9C%A8%20C%20%E7%A8%8B%E5%BA%8F%E4%B8%AD%E5%88%9B%E5%BB%BA%E7%9A%84%20Bash%20%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%91%BD%E5%90%8D%E7%AE%A1%E9%81%93.png)
我有一个需要相当大输入的 C 代码。在每次迭代中,它都会处理其中的一小块,并且应该使用curl 将处理后的块发送到 S3。最后,它将生成许多小块,并且大输入将被完全处理。我遇到问题的地方是 bash 脚本调用命名管道的部分,我使用命名管道将处理后的块单独发送到 S3。
如何在 C 中调用 bash 脚本以及如何使用 bash 将命名管道内的数据发送到curl?
我只会分享代码的相关部分以保持简洁。
#define FIFO_NAME "my_fifo"
int i,j,k;
char *d_ptr; //dummy pointer for frame set
int res;
/* create the FIFO (named pipe) */
if (access(FIFO_NAME, F_OK) == -1) {
res = mkfifo(FIFO_NAME, 0777);
if (res != 0)
{
fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
}
res = open("test_fifo", O_WRONLY);
d_ptr=(char *) compressed_queue;
if(m_ptr-m_ptr_initial==0 | m_ptr-m_ptr_initial>MAX_MESSAGE_LENGTH-FLENGTH*sizeof(float) | number_of_frames>MAX_FRAME_NUMBER)//sends message when the chunk is ready and adds its prefix
{
for(j=0;j<m_ptr-m_ptr_initial;j++)//sends message as stdout
{
/* write to the FIFO */
write(res, m_ptr_initial[j], sizeof(char));
}
if (res != -1)
(void)close(res);
另外,bash 脚本如下。
#!/bin/bash
while true
do
TIMER=renesas-$(date +"%H-%M-%S").txt
echo $TIMER
./Compression
my_fifo| curl -X PUT --data-binary @- 54.231.19.24/{somePublicBucket}/device1/${TIMER}
done
答案1
您的代码中有两个错误:
write(…, sizeof(char));
只会将“sizeof(char)”字节(= 最有可能的 1 或 2 个字节)写入 FIFO,而不是您可能想要的缓冲区大小my_fifo |
不会从 FIFO 读取任何数据;你cat
至少需要它。
由于调用write
将阻塞,直到脚本读取数据(反之亦然!),我建议将写操作和脚本的执行放入两个不同的进程或线程中(还有其他可能性,例如非阻塞写;这完全取决于您的预期设计)。下面的例子演示了原理,fork
为了简单起见,使用系统调用:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#define FIFO_NAME "./my_fifo"
int main() {
int res, fifo, pid;
char *str = "Hello World!\n";
/* Fork this process into a reader and a writer */
fprintf(stderr, "Forking process\n");
pid = fork();
assert(pid >= 0);
if (pid == 0) {
/* The reader calls a shell script supposed to read the data from the FIFO */
printf("Starting shell script\n");
system("./tst.sh");
}
else {
/* Create FIFO */
fprintf(stderr, "Creating FIFO\n");
remove(FIFO_NAME);
res = mkfifo(FIFO_NAME, 0777);
assert(res == 0);
/* Open FIFO */
fprintf(stderr, "Opening FIFO\n");
fifo = open(FIFO_NAME, O_WRONLY);
assert(fifo != 0);
/* The writer opens the FIFO and writes some data to it */
printf("Writing to FIFO\n");
res = write(fifo, str, strlen(str));
assert(res > 0);
close(fifo);
}
}
shell脚本tst.sh
包含:
#!/bin/sh
echo "Started shell script"
cat ./my_fifo
C 程序的输出为:
Forking process
Creating FIFO
Opening FIFO
Starting shell script
Started shell script
Writing to FIFO
Hello World!