Использование execv без списка параметров - PullRequest
0 голосов
/ 25 марта 2020

Я бы хотел использовать форк из моей основной программы для создания экземпляра процесса другой программы, которую я написал. Вот пример того, что я пытаюсь сделать:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>

    int main(int argc, char *argv[]){
    char *ar[] = {"./myfile",NULL};

    switch (fork()) {
        case -1:
            printf("Problem.\n");
            break;
        case 0:
            printf("Everything ok...\n");
            execv("./myfile",ar);
            printf("err\n");
            exit(1);
        default: 
            sleep(1);
    }
    return 0;
}

Это моя основная программа. Программа myfile выглядит следующим образом:

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <signal.h> 
    #include <unistd.h>

int main(int argc, char *argv[]){
    printf("Hi!\n");
    return 0;
}

Это вывод, который я ожидаю:

Everything ok...
Hi!

Но я получаю только:

Everything ok...

Что я делаю неправильно? execv принимает два параметра, но второй в моем случае пуст (или NULL?). Я пытался добавить строку

char *argv[] = NULL;

в основную программу, но получил ошибку, потому что не могу сделать это в C.

Ответы [ 3 ]

1 голос
/ 26 марта 2020

execv принимает два аргумента, а второй, согласно man-странице, должен быть:

массив указателей на строки с нулевым символом в конце, которые представляют список аргументов, доступных для новая программа. Первый аргумент, по соглашению, должен указывать на имя файла, связанное с исполняемым файлом. Массив указателей должен заканчиваться нулевым указателем.

Поэтому у вас должно быть что-то вроде:

char *argv_for_program[] = { filename, NULL };
execv(filename, argv_for_program);

Некоторые другие примечания:

  • Ваш printf, непосредственно предшествующий execv, не заканчивается новой строкой. Поскольку stdout обычно представляет собой строковый буфер , текст "Everything ok..." не будет напечатан, пока буфер не будет очищен. И execv заменяет вашу программу на ./myfile без очистки буферов, поэтому сообщение "Everything ok..." теряется. Чтобы исправить это, вместо этого выведите "Everything ok...\n" или позвоните fflush(stdout) до execv.

  • execv, только если вы не смогли выполнить программу , В этом случае, вероятно, не желательно exit(EXIT_SUCCESS); было бы лучше напечатать соответствующее сообщение об ошибке (например, с perror) и выйти с кодом ошибки.

  • Как отмечено в комментариях, вам нужно #include <unistd.h>.

0 голосов
/ 26 марта 2020

Если вы хотите предоставить аргументы через argv[] (как вы указали в своих комментариях), это упрощает переход к execv, если вы предоставляете Full-Path для программа для запуска в качестве первого аргумента и любой аргумент для передачи этой программе после этого. argv - это уже массив указателей с первым указателем после последнего предоставленного пользователем аргумента, установленного на NULL. Вы просто начинаете индексирование с argv[1] (argv[0] - это всегда текущая программа, запускаемая, argv[1] первый предоставленный пользователем аргумент). Вы можете сделать что-то простое:

#include <stdio.h>
#include <unistd.h>

int main (int argc, char **argv) {

    if (argc < 2) {
        fprintf(stderr, "error: insufficient input.\n"
                        "usage: %s full-path-prog [arg1, arg2, ...]\n", argv[0]);
        return 1;
    }

    execv (argv[1], &argv[1]);      /* call execv with argv[] */
}

( примечание: в случае успеха, execv не возвращается, новый процесс заменяет текущий, в случае неудачи вы должны на самом деле вызвать _exit();, чтобы избежать UB в угловом случае, если вы установили atexit() функции или деструкторы - здесь не имеет значения)

Пока вы предоставляете правильное имя утилиты и аргументы (не включая перенаправления и т. д. c ..), код просто передает утилиту в execv и будет выполняться с любыми предоставленными дополнительными аргументами, например,

Пример использования / Вывод

Предоставление полного пути к программе и любых аргументов, например

$ ./bin/execv_simple /bin/ls -al /home/david/tmp
total 1163032
drwxr-xr-x 44 david david         20480 Mar 23 13:35  .
drwxr-xr-x 68 david david          4096 Mar 25 02:36  ..
drwxr-xr-x  2 david david          4096 Nov  7 22:30  .qt
-rw-r--r--  1 david david       4534793 Nov  4 19:31  .xsession-errors
...

$ ./bin/execv_simple /usr/bin/df -h
Filesystem     1K-blocks     Used Available Use% Mounted on
devtmpfs         4043708        0   4043708   0% /dev
tmpfs            4055092    11964   4043128   1% /dev/shm
tmpfs            4055092     1716   4053376   1% /run
tmpfs            4055092        0   4055092   0% /sys/fs/cgroup
/dev/sdb2       41156156 25400864  13641604  66% /
tmpfs            4055092       60   4055032   1% /tmp
/dev/sdb3      437217592 43731284 392581260  11% /home
tmpfs             811016        8    811008   1% /run/user/1000

$ ./bin/execv_simple /usr/bin/free
              total        used        free      shared  buff/cache   available
Mem:        8110188     2147572     4048728       53432     1913888     5594460
Swap:       2103292           0     2103292

( примечание: вы можете использовать подстановку команд с type -p или which для предоставления полного имени программы, например, ./bin/execv_simple $(type -p free) будет заполнять полный путь информации для вас)

Аргументы не предоставлены: * 103 9 *

$ ./bin/execv_simple
error: insufficient input.
usage: ./bin/execv_simple full-path-prog [arg1, arg2, ...]

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 25 марта 2020

Без завершающего перевода строки вывод из любого из вашей программы s не гарантированно будет отображаться так, как вы ожидаете. Всегда выводить завершающий '\n'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...