Как передать параметры и использовать их, используя exec в C? - PullRequest
0 голосов
/ 30 сентября 2019

Я хотел бы начать новый процесс с каждого из моих дочерних процессов и сделать так, чтобы они добавляли числа, передаваемые в качестве параметров через exec(). Что-то вроде этого. Я просто не знаю, как я могу получить доступ к параметрам в новом процессе.

code.c

#include <stdio.h>
#include <stdlib.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <time.h>
# include <stdlib.h>
# include <dirent.h>
# include <stdio.h>
# include <string.h>
# include <getopt.h>
# include<stdbool.h>
# include <ctype.h>
# include<sys/wait.h>
# include<signal.h>
# include <sys/mman.h>
# include<sys/time.h>

void forking()
{ int a=4,b=5
for (int i=0;i<4;i++)
pid_t pID = fork();

                   if (pID == 0)  
                   {
                    static char *argv[]={a,b,NULL};
                                    execv("/EXEC.c",argv);
                   } 
                   else
                     wait(pID);

}

void main(int argc, char **argv)
{
    forking();
}

EXEC.c

#include <stdio.h>
#include <stdlib.h>
# include <stdio.h>
# include <string.h>
int main()
{
    //Code to add a and b and print the sum
    printf("%d",a+b);
}

1 Ответ

3 голосов
/ 30 сентября 2019

В показанном коде много проблем:

  • Не компилируется.
  • Вы не должны писать /EXEC.c в корневом каталоге. .

    • Не записывать в корневой каталог.
    • Не запускать от имени root.
    • Только root должен иметь возможность писать в корневой каталог.
    • Запуск от имени пользователя root опасен и его следует избегать.
  • Не вызывайте исполняемые программы с именами, похожими на исходный код - EXEC.c обычно будетC исходный файл, а не программа, которая может быть выполнена;вам нужно создать и запустить EXEC из EXEC.c.
  • Некоторые добавят «не кричите» - чаще всего все имена программ пишутся строчными или в основном строчными буквами;они редко бывают в верхнем регистре, как показано.
  • В этом случае компиляция exec.c для создания exec будет работать плохо ОК , потому что даже при exec - это встроенная команда оболочки, которая не ищется на диске. Использование /path/to/exec (или даже ./exec) будет работать, но потребуется некоторый путь (хотя бы один /). Поскольку вы используете execv(), ядро ​​(а не оболочка) будетвыполнить программу напрямую. Тем не менее, вы все равно должны использовать другое имя - есть возможность для путаницы.
  • Также не используйте test в качестве имени для ваших программ - это еще одна встроенная оболочка и вызов вашей собственной программы test рано или поздно приводит к путанице, обычно раньше.
  • См. Что должно main() вернуть в C и C ++ - вы должны использовать int main(void) или int main(int argc, char **argv) (интересно,Вы должны использовать более короткий вариант в code.c и более длинный в EXEC.c, но у вас они есть в обратном направлении.)
  • Вы получаете доступ к аргументам, передаваемым в вашу программу через argc и argv - аргументыявляются строками.
  • Вы передаете аргументы исполняемым программам как строки, а не как простые целые числа, как вы пытаетесь сделать с static char *argv[]={a,b,NULL}; (где a и b имеют тип int). Вы должны получать предупреждения компилятора, если нет ошибок из этого.
  • Вы должны передать имя программы как argv[0], а рабочие аргументы как argv[1] и argv[2] - вы правильно добавите NULL до конца списка аргументов.
  • Не следует включать все заголовки, которые вы можете придумать в code.c - вы должны включать только те, которые используете.
  • Вы не должныповторите <stdio.h> или <stdlib.h>.
  • Вы должны быть последовательны в своем интервале - желательно, следуя схеме вашего первого #include <stdio.h> line (без пробелов между # и include; один пробел между include и <stdio.h>; обычно нет пробелов, хотя комментарий допускается, если он считается полезным и ему должен предшествовать пробел).
  • В printf() в EXEC.c должна быть новая строка наконец строки формата.
  • Код в forking() не компилируется, потому что тело цикла for равно pid_t pID = fork(); - и вы не можете иметь определение переменной в качестве телапетля без окружающих скобок. Кроме того, pID не будет определен для оператора if, если только он не находится в теле цикла. Кроме того, определения a и b не заканчиваются точкой с запятой.
  • Вы должны иметь exit() некоторого рода после execv(), желательно с сообщением об ошибке, на всякий случайexecv() терпит неудачу.
  • Вызов wait() неверен - wait() ожидает аргумент int указателя, а не простой int.

Возможнобыть и другие проблемы, которые исправляются мимоходом. Пересмотренный код ниже представляет собой два файла, parent.c и child.c. Код предполагает, что программа child находится в текущем каталоге (поэтому ./child выполнит ее). Вы запускаете parent;он создает дочерние процессы.

parent.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

static void forking(void)
{
    for (int i = 0; i < 4; i++)
    {
        pid_t pID = fork();

        if (pID == 0)
        {
            static char *args[] = { "./child", "4", "5", NULL };
            execv(args[0], args);
            fprintf(stderr, "Failed to execute %s\n", args[0]);
            exit(EXIT_FAILURE);
        }
        else if (pID < 0)
        {
            fprintf(stderr, "Failed to fork()\n");
            exit(EXIT_FAILURE);
        }
        else
        {
            int corpse;
            int status;
            while ((corpse = wait(&status)) > 0)
            {
                printf("Process %d exited with status 0x%.4X\n", corpse, status);
                if (corpse == pID)
                    break;
            }
        }
    }
}

int main(void)
{
    forking();
    return 0;
}

child.c

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s number1 number2\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    long number1 = strtol(argv[1], 0, 0);
    long number2 = strtol(argv[2], 0, 0);
    printf("%ld\n", number1 + number2);
    return 0;
}

Строго, код должен проверять, что strtol() работает, но делаеттак правильно - просто Правильное использование strtol()? для получения более подробной информации.

Пример вывода

$ ./parent
9
Process 14201 exited with status 0x0000
9
Process 14202 exited with status 0x0000
9
Process 14203 exited with status 0x0000
9
Process 14204 exited with status 0x0000
$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...