Форк не загружает программу в execv
Программа ниже не загружает программу в дочерний процесс и не печатает "до" и "после". Однако ps aux показывает создание процессов (но без загрузки программы args0). Я использую ТРУБУ, определенную как socketpair. args0[] содержит имя исполняемой программы для дочерней программы, args1[] содержит имя дочерней программы. args2 и args3 являются предопределенными значениями, которые не изменяются и должны быть отправлены дочерним элементам в качестве аргументов. вы можете считать, что char args2[] = "10" -> пользовательский ввод (цифра) и преобразован в строку. Я просто не понимаю, почему хотя бы printf("до") не печатается. я читал о fflush и помещал \n в каждый printf, и я сделал. так что все в моей программе напечатано правильно до этого момента.
Буду очень признателен за ваши ответы.
char args2[];
char args3[];
//creating pipe
int forkk(pipes *myPipe, server_message *m, char args0[],char args1[]) {
pid_t cpid;
//pipe passed myPipe[i]
if (PIPE(myPipe->fd) == -1) {
perror("pipe error\n");
return -1;
}
fork();
cpid=getpid();
if (cpid == -1) {
perror("fork error\n");
return -1;
}
if (cpid) {
close(myPipe->fd[1]);
return 1;//closing one end of parent
} else {
for (int i = 3; i <= myPipe->fd[0]; i++) {
close(i);
}
dup2(myPipe->fd[1], 0); //redirecting stdin of child
dup2(myPipe->fd[1], 1); //redirecting stdout of child
close(myPipe->fd[1]);
myPipe->cpid = cpid;
char *newargs[3];
newargs[0]=args1;
newargs[1]=args2;
newargs[2]=args3;
printf("before\n");
//fflush(stdout);
execv(args0,newargs);
printf("after execv\n");
write(myPipe->fd[0], &m, sizeof(server_message)); //send the server_msg immediately (pass an array or msg)
}
return 2;
}
void main(){
....
scanf("%d %d", &width, &height);
sprintf(args2,"%d",height); //converting into to string
sprintf(args3,"%d",width);
char *args0 = "./prey";
char *args1 = "prey";
int r= forkk(&myPipes[2], &msg, args0,args1);
}
Я не могу опубликовать весь код, так как он длинный и требует объяснения. Скорее всего, у меня проблема с назначением указателя, что я ошибочно считаю правильным способом. Большое спасибо за любую помощь
1 ответ
(спойлер: твой else
филиал в вашем плохо названном forkk
никогда не берется!)
Внимательно прочитайте документацию execv (3). Вы должны предоставить NULL
прекращенный массив.
Функции execv(), execvp() и execvpe() предоставляют массив указателей на строки с нулевым символом в конце, которые представляют список аргументов, доступных для новой программы. Первый аргумент, по соглашению, должен указывать на имя файла, связанное с исполняемым файлом. Массив указателей должен заканчиваться нулевым указателем.
Так что вы должны хотя бы кодировать:
char *newargs[4];
newargs[0]=args1;
newargs[1]=args2;
newargs[2]=args3;
newargs[3] = NULL; // mandatory last NULL pointer
execv(args0,newargs);
Кстати, первый аргумент обычно должен быть именем программы. Итак, вы действительно хотите:
char *newargs[5];
newargs[0] = args0;
newargs[1]=args1;
newargs[2]=args2;
newargs[3]=args3;
newargs[4] = NULL; // mandatory last NULL pointer
execv(args0,newargs);
И в документации тоже сказано
Функции exec() возвращаются, только если произошла ошибка.
Так что в большинстве случаев нет смысла продолжать здесь, так как execv
не вернется в случае успеха Однако вам нужно поймать неудачу. Я рекомендую после вашего execv
perror(arg0); // or perhaps perror("execv");
exit(EXIT_FAILURE);
Ваш write(myPipe->fd[0], &m, sizeof(server_message));
очень плохо пахнет. Я не вижу смысла делать это (только), когда execv
терпит неудачу
Кстати, с помощью strace(1) вы, вероятно, поймали бы такую ошибку (пропуская завершение NULL
указатель для execv
).
Наконец, вы всегда должны сохранять результат fork (2). Смотрите это. Так что замените:
fork(); // WRONG
cpid=getpid(); // always positive!
с cpid = fork();
Конечно, вам нужно разобраться с тремя случаями: cpid== -1
(что вы забыли обработать!), cpid== 0
, cpid> 0
,
Опять же, внимательно прочитайте getpid (2):
getpid () возвращает идентификатор процесса (PID) вызывающего процесса.
и о getpid
& getppid
):
Эти функции всегда успешны
Так getpid
никогда не возвращает 0 (и именно поэтому ваш else
филиал в вашем forkk
плохо названная функция, содержащая execvp
никогда не запускается). Смотрите также полномочия (7).
Ваш void main()
тоже неправильно. main
должен вернуть int
, Вы обычно определяете это как int main(int argc, char**argv)
...
PS. Возьмите за правило внимательно читать документацию по каждой функции, которую вы используете.
Ваш forkk
очень плохо назван, слишком похож на очень важный fork
название.