程序的参数必须都是字符串。
因此,要将信号量 ID、共享内存 ID 和文件描述符传递给执行程序,您需要调用程序代码将数字转换为字符串,然后执行程序将字符串转换回数字,然后使用适当的。
您的代码没有显示 'pipe2'...我假设它是一个简单的 int,但如果它是一个数组(如 pipe1 是),那么您需要用 0 或1 获取相关文件描述符:
char shmarg[20];
char semarg[20];
char piparg[20];
int semid = semget (key1, 4, IPC_CREAT | 0666);
int shmid = shmget(key2, 1024, 0644 | IPC_CREAT);
int pipe1[2];
const char *cmd = "/home/tropix/program-3";
if (pipe(pipe1))
{
printf("Failed to create pipe: %s\n", strerror(errno));
exit(1);
}
snprintf(shmarg, sizeof(shmarg), "%d", shmid);
snprintf(semarg, sizeof(semarg), "%d", semid);
snprintf(piparg, sizeof(piparg), "%d", pipe2);
execl(cmd, cmd, semarg, shmarg, piparg, (char*)0);
fprintf(stderr, "File Execution of program 3 failed.\n");
exit(1);
不清楚为什么要创建pipe1;你需要用它做适当的管道。如果execl() 返回,则失败。你不需要测试它的返回值。
来自cmets:
[I'm] 只是为了简单起见删除了相关部分 [...] [Im] 不确定您所说的 pipe1 的“适当管道”是什么意思?你能告诉我应该怎么做,或者让我参考一些关于如何初始化管道并将其传递给下一个文件的信息吗?我意识到在需要它的程序中创建管道可能是一个更好的选择,但在这种情况下,需要在程序 1 中对其进行初始化。
问题的简单性是个好主意...
我假设在对pipe() 和execl() 的调用之间,有一个fork() 被省略了。否则,pipe() 毫无意义。
据推测,创建管道的目的是让子进程与父进程对话,或者让父进程与子进程对话。有双向管道,但它们既不是标准的也不是便携式的;因此,我假设您有一个常规的单向管道。由于您将文件描述符编号作为参数传递给子节点,因此我们不会为子节点重定向标准输入或标准输出 - 这是您经常(但不总是)使用管道执行的操作。
因此,您修改后的代码可能是(删除空白行以避免滚动条):
char shmarg[20];
char semarg[20];
char piparg[20];
int semid = semget(key1, 4, IPC_CREAT | 0666);
int shmid = shmget(key2, 1024, 0644 | IPC_CREAT);
int pipe1[2];
const char *cmd = "/home/tropix/program-3";
if (pipe(pipe1))
{
printf("Failed to create pipe: %s\n", strerror(errno));
exit(1);
}
pid_t pid = fork();
if (pid < 0)
err_exit("Failed to fork");
else if (pid > 0)
{
/* Do parental things */
close(pipe1[0]);
...write to pipe1[1]...
}
else
{
/* Do childish things */
/* Assuming child is reading from pipe */
close(pipe1[1]);
snprintf(shmarg, sizeof(shmarg), "%d", shmid);
snprintf(semarg, sizeof(semarg), "%d", semid);
snprintf(piparg, sizeof(piparg), "%d", pipe1[0]);
execl(cmd, cmd, semarg, shmarg, piparg, (char*)0);
fprintf(stderr, "File Execution of program 3 failed.\n");
exit(1);
}
显然,如果管道由父级读取并由子级写入,则需要兼顾关闭和指定的文件描述符编号。
几乎总是,您最终会关闭从pipe() 返回的两个文件描述符中的至少一个。如果将管道重定向到标准输入或标准输出,通常使用dup2() 复制管道的相应端,然后关闭从pipe() 返回的两个文件描述符。由于所有这些都在弄乱管道,因此通俗地称为管道。