Все аргументы программы должны быть строками.
Следовательно, для передачи идентификатора семафора, идентификатора совместно используемой памяти и дескриптора файла в исполняемую программу необходим код вызывающей программы для преобразования чисел в строкии исполняемая программа для преобразования строк обратно в число, которое затем соответствующим образом использует.
Ваш код не показывает 'pipe2' ... Я предположил, что это был простой int
, но еслиэто был массив (например, pipe1
is), тогда вам нужно добавить его в 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()
возвращается, это не удалось.Вам не нужно проверять его возвращаемое значение.
Из комментариев:
[Я] просто вырезать соответствующие разделы для простоты [...] [Я] не уверен, что ты имеешь в виду под «подходящей сантехникой» с 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()
.Поскольку все это портит трубы, в разговорной речи это называется сантехника.