У меня есть пример программы, которая принимает входные данные из терминала и выполняет их в клонированном дочернем элементе в подоболочке.
#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/wait.h>
#include <sched.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
int clone_function(void *arg) {
execl("/bin/sh", "sh", "-c", (char *)arg, (char *)NULL);
}
int main() {
while (1) {
char data[512] = {'\0'};
int n = read(0, data, sizeof(data));
// fgets(data, 512, stdin);
// int n = strlen(data);
if ((strcmp(data, "exit\n") != 0) && n > 1) {
char *line;
char *lines = strdup(data);
while ((line = strsep(&lines, "\n")) != NULL && strcmp(line, "") != 0) {
void *clone_process_stack = malloc(8192);
void *stack_top = clone_process_stack + 8192;
int clone_flags = CLONE_VFORK | CLONE_FS;
clone(clone_function, stack_top, clone_flags | SIGCHLD, (void *)line);
int status;
wait(&status);
free(clone_process_stack);
}
} else {
exit(0);
}
}
return 0;
}
Приведенный выше код работает в старой системе Linux (с минимальным объемом ОЗУ (но не в более новой. Не работает означает, что если я набираю простую команду, такую как "ls" , я не вижу вывод на консоли. Но в более старой системе я вижу ее.
Кроме того, если я запускаю тот же код на gdb в режиме отладчика, тогда я вижу вывод, напечатанный на консоли в более новой системе.
Кроме того, если я использую fgets () вместо read () работает в обеих системах, как и ожидалось, без проблем.
Я пытался понять поведение и не смогЯ попытался сделать strace . Разница, которую я вижу в том, что возврат wait () имеет вывод программы ls в тех случаях, когдаработает и ничего для случаев это не работает.
Единственное, что я могу думать о себеs, что read (), так как не библиотечная функция имеет неопределенное поведение в разных системах.Но я не могу согласиться с тем, как это влияет на результат.
Может кто-то указать мне, почему я могу наблюдать это поведение?
РЕДАКТИРОВАТЬ
Код скомпилирован как:
gcc test.c -o test
strace, когда он не работает должным образом, как показано ниже
strace, когда он работает как положено (единственное отличие - я добавил printf ("% d \ n", n); после вызова read () )
Спасибо
Шабир