как работает popen2() в c?

Я пытаюсь выполнить команду md5sume в своей программе, используя pipe, fork и dup. Я нашел код суммы, который работает успешно, но я не могу понять какую-то строку кода. Вот мой код:

int infp, outfp;

char buf[128];

if (popen2("md5sum", &infp, &outfp) <= 0)

  {

    printf("Unable to exec sort\n");

    exit(1);

  }

write(infp, "hello\n", 2);

close(infp);

*buf = '\0';

read(outfp, buf, 128);

printf("buf = '%s'\n", buf);

return 0;

}

int p_stdin[2], p_stdout[2];

pid_t pid;

if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)

  return -1;

pid = fork();

if (pid < 0)

  return pid;

if (pid == 0)

  {

    close(p_stdin[WRITE]);

    dup2(p_stdin[READ], READ);

    close(p_stdout[READ]);

    dup2(p_stdout[WRITE], WRITE);

    execl("/bin/sh", "sh", "-c", command, NULL);

    perror("execl");

    exit(1);

  }

else 

  {

if (infp == NULL)

    close(p_stdin[WRITE]);

else

    *infp = p_stdin[WRITE];

if (outfp == NULL)

    close(p_stdout[READ]);

else

    *outfp = p_stdout[READ];
  }

return pid;

}

я не понимаю функцию popen. Что именно делает эта строка?

*infp = p_stdin[WRITE];

как трубы могут сообщаться друг с другом?


person farzane    schedule 04.11.2015    source источник
comment
Отформатируйте код! Удалите ненужные пустые строки.   -  person too honest for this site    schedule 04.11.2015
comment
Вы говорите оpopen2(), а не о popen(), я думаю. Я также предполагаю, что 2-й блок кода — это функция popen2(). Вы должны обратиться к man 2 pipe и прочитать описание. Канал представлен двумя файловыми дескрипторами, один для записи и один для чтения. То, что вы пишете в нем, может быть прочитано из него. После fork() один из процессов может писать в него, а другой читать из него, поэтому они взаимодействуют.   -  person hexasoft    schedule 04.11.2015
comment
да, я знал это. А также я знал, что это была функция popen2. Но я не могу понять использование целого числа для реализации двунаправленного канала, и этого не было в человеке !!   -  person farzane    schedule 07.11.2015


Ответы (1)


я не понимаю функцию popen.

как трубы могут сообщаться друг с другом?

pipe() : канал является однонаправленным и является буфером потока байтов в ядре. Поскольку это поток байтов, записывающий может записывать произвольное количество байтов, а считыватель может считывать произвольное количество байтов. Однако обратите внимание, что последовательное чтение возможно, но поиск (например, lseek) невозможен. Поскольку канал является однонаправленным, данные, записываемые в канал, должны буферизоваться в ядре до тех пор, пока они не будут прочитаны с конца канала для чтения. Кроме того, если канал заполняется, запись блокируется.

Предположим, что fd — это целочисленный массив из двух файловых дескрипторов (int fd[2]), тогда системный вызов pipe(fd) должен создать канал и вернуть пару файловых дескрипторов, таких что fd[1] (stdout равен 1) должен быть концом канала записи, а fd[0] (stdin равен 0) должен быть концом канала чтения. В отличие от именованного канала (например, FIFO — канала с именем в файловой системе), анонимные каналы могут использоваться только между связанными процессами, такими как родитель-потомок. Таким образом, необходимо выполнить разветвление, чтобы дублировать эти 2 родительских файловых дескриптора в дочернем, тем самым родитель разделяет канал с дочерним, так что дочерний элемент должен писать в конец записи, а родитель должен читать из конца чтения канала, или родитель должен записывать в запись- end и потомок должен читать из read-end канала. Следует позаботиться о том, чтобы неиспользуемый файловый дескриптор чтения (fd[0]) / неиспользуемый файловый дескриптор записи (fd[1]) закрывался родительским или дочерним элементом в соответствии со сценарием.

popen() : popen позволяет вам вызывать другую программу как новый процесс и тем самым передавать ей данные или получать данные от нее. В случае popen обратите внимание, что направление потока данных основано на втором аргументе. Нам не нужно вручную создавать дочерний процесс, так как popen автоматически разветвляется для создания дочернего процесса, запускает оболочку и выполняет аргумент команды, переданный через popen. Он также автоматически устанавливает соответствующий поток чтения или записи между родительским и дочерним элементами на основе аргумента типа.

Таким образом, popen() упрощает работу, поскольку позволяет избежать необходимости вручную вызывать/вызывать pipe, fork, exec и упрощает автоматическое установление соответствующих потоков между родителем/потомком в соответствии с типом аргумента. Однако следует отметить, что другая сторона popen заключается в том, что каждый вызов popen() должен приводить к созданию дополнительного процесса, то есть оболочка вызывается каждый раз, кроме вызываемой программы, которая вызывается. свою очередь приводит к высокому потреблению ресурсов.

person Karthik Balaguru    schedule 04.11.2015
comment
Я знал об этом. Моя основная проблема была в двунаправленном канале. Вы знаете, что в popen мы можем просто установить w или r настроение во втором параметре, но в моей программе мне нужно использовать настроение rw. Поэтому мне нужен двунаправленный канал! - person farzane; 07.11.2015
comment
труба однонаправленная. popen поддерживает только «r» или «w» и не поддерживает другие параметры, такие как «чтение и запись». В случае требования двунаправленной связи с использованием каналов вам может потребоваться реализовать два канала, по одному для каждого направления. - person Karthik Balaguru; 17.11.2015