Передать файловый дескриптор — Execve (приведение типов)

Мне интересно, как я могу передать дескриптор файла через команду execve(), а затем получить к нему доступ с другой стороны. Я знаю, что могу использовать dup2 для перенаправления дескриптора файла, но я не могу этого сделать. Я должен фактически передать дескриптор файла дочернему элементу и использовать его в дочернем элементе.

Что я сделал до сих пор:

Родитель создает pipe + аргументы следующим образом:

int pfd[2];
if(pipe(pfd) == -1)
    exitWithError("PIPE FAILED", 1);
char *args_1[] = {"reader", argv[1], (char*) pfd, (char *) 0};

Затем ребенок вызывает execve после fork() следующим образом:

close(pfd[1]);
execve("./reader", args_1, NULL);

Затем в программе чтения я пытаюсь получить доступ к переданному дескриптору канала:

int main(int argc, char* argv[]){
    ...
    write(argv[2][1], buf, read_test);

argv[2] должен ссылаться на дескриптор канала, тогда argv[1] должен идти к концу записи канала. Я почти уверен, что здесь мне нужно сделать приведение типов по-другому, но все, что я пытаюсь сделать, не совсем работает.

ПРИМЕЧАНИЕ. У меня есть рабочая версия этой программы, использующая dup2 для перенаправления на stdin и stdout для дочерних элементов, но я должен фактически передать дескриптор канала дочернему элементу в соответствии с инструкциями проекта.

Любая помощь приветствуется.


person forTruce    schedule 12.09.2011    source источник


Ответы (1)


Простое приведение файлового дескриптора к char* не является хорошей идеей. Это может привести к потере данных, если ОС решит скопировать строки и остановится на 0 байтах, поэтому данные не будут скопированы полностью. Было бы безопаснее создать строку, содержащую дескриптор файла.

int pfd[2];
if(pipe(pfd) == -1)
    exitWithError("PIPE FAILED", 1);
char string1[12]; // A 32 bit number can't take more than 11 characters, + a terminating 0
snprintf(string1,12,"%i",pfd[1]); // Copy the file descriptor into a string
char *args_1[] = {"reader", argv[1], &string1[0], (char *) 0};

Затем программа чтения использует atoi, чтобы преобразовать это обратно в целое число.

int fd = atoi(argv[2]);
write(fd,buf,read_test);

Если вы действительно хотите использовать приведение типов, вам нужно преобразовать argv[2] в int* в вашем ридере.

write(((int*)argv[2])[1],buf,read_test);
person ughoavgfhw    schedule 12.09.2011
comment
Спасибо большое. Я все еще пытаюсь понять, что на самом деле произошло в этой транзакции (приведение типов меня немного смущает), но ваш пост очень ясен, и я думаю, что понимаю. - person forTruce; 12.09.2011