Проблемы с вызовами system () в Linux - PullRequest
1 голос
/ 16 июня 2010

Я работаю над init для initramfs в C ++ для Linux. Этот сценарий используется для разблокировки зашифрованного диска DM-Crypt w / LUKS и настройки доступности дисков LVM.

Поскольку я не хочу переопределять функциональность cryptsetup и gpg, я использую системные вызовы для вызова исполняемых файлов. Использование системного вызова для вызова gpg работает нормально, если у меня уже полностью запущена система (у меня уже есть initramfs на основе сценария bash, который прекрасно работает при его запуске, и я использую grub для редактирования командной строки, чтобы вызвать ее с помощью старые initramfs). Однако в initramfs он никогда не действует так, как его вызывают. Даже такие команды, как system("echo BLAH"); терпят неудачу.

Итак, у кого-нибудь есть вход?


Редактировать: Итак, я выяснил, что стало причиной моих ошибок. Я не имею понятия о , почему это приведет к ошибкам, но я нашел это.

Чтобы разрешить горячее подключение, мне нужно было записать /sbin/mdev в /proc/sys/kernel/hotplug ... однако я закончил переключением параметров (для функции, которую я сам написал не меньше), поэтому я писал /proc/sys/kernel/hotplug в /sbin/mdev.

Я понятия не имею, почему это может вызвать проблему, однако это так и было.

Ответы [ 3 ]

6 голосов
/ 17 июня 2010

Амардип прав, system() в системах типа POSIX запускает команду через /bin/sh.

Я сомневаюсь, что у вас действительно есть законная необходимость вызывать эти программы, о которых вы говорите, через оболочку Bourne. Хорошей причиной было бы, если бы вы хотели, чтобы они имели набор переменных окружения по умолчанию, но, поскольку /etc/profile, вероятно, также недоступен на ранних этапах процесса загрузки, я не понимаю, как это может быть здесь.

Вместо этого используйте стандартный шаблон fork()/exec():

int system_alternative(const char* pgm, char *const argv[])
{
    pid_t pid = fork();
    if (pid > 0) {
        // We're the parent, so wait for child to finish
        int status;
        waitpid(pid, &status, 0);
        return status;
    }
    else if (pid == 0) {
        // We're the child, so run the specified program.  Our exit status will
        // be that of the child program unless the execv() syscall fails.
        return execv(pgm, argv);
    }
    else {
        // Something horrible happened, like system out of memory
        return -1;
    }
}

Если вам нужно прочитать стандартный вывод из вызываемого процесса или отправить данные на его стандартный ввод, вам нужно будет выполнить некоторое перенаправление стандартного дескриптора через pipe() или dup2().

Вы можете узнать все об этом в любой хорошей книге по Unix. Я рекомендую Расширенное программирование в среде UNIX от У. Ричарда Стивенса. Второе издание, соавтором которого является Rago, добавляет материал для платформ, появившихся после того, как Стивенс написал первое издание, таких как Linux и OS X, но основы, подобные этой, не изменились со времени первоначального выпуска.

6 голосов
/ 16 июня 2010

Я считаю, что функция system () выполняет вашу команду в оболочке. Монтируется и доступен ли исполняемый файл оболочки на ранних этапах процесса запуска? Возможно, вы захотите изучить использование fork () и execve ().

РЕДАКТИРОВАТЬ: Убедитесь, что ваши криптографические инструменты также находятся на подключенном томе.

1 голос
/ 16 июня 2010

что у вас есть в initramfs?Вы можете сделать следующее:

int main() {
   return system("echo hello world");

}

И затем поместить его в начальный текст, подобный этому:

strace -o myprog.log myprog

Посмотрите журнал после загрузки вашей системы

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