Może ktoś wyjaśnić co robi dup () w C?

Wiem, że dup, dup2, dup3 "tworzy kopię deskryptora pliku oldfd "(ze stron podręcznika). Jednak nie mogę go przetrawić.

Jak wiem deskryptory plików są po prostu liczbami , aby śledzić lokalizacje plików i ich kierunek(wejście/wyjście). Wouldn ' t it be easier to just

fd=fd2;

Kiedy chcemy powielić deskryptor pliku?

I coś jeszcze..

dup () używa najniższego nieużywanego deskryptora dla nowego deskryptor.

Czy to oznacza, że może również przyjmować wartość stdin, stdout lub stderr jeśli założymy, że mamy close () -ed jeden z nich?

Author: Pithikos, 2011-10-22

7 answers

Chciałem odpowiedzieć sobie na drugie pytanie po odrobinie eksperymentów.

Odpowiedź brzmi Tak . Utworzony deskryptor pliku może przyjmować wartość 0, 1, 2, jeśli stdin, stdout lub stderr są zamknięte.

Przykład:

close(1);     //closing stdout
newfd=dup(1); //newfd takes value of least available fd number

Gdzie to się dzieje z deskryptorami plików:

0 stdin     .--------------.     0 stdin     .--------------.     0 stdin
1 stdout   =|   close(1)   :=>   2 stderr   =| newfd=dup(1) :=>   1 newfd
2 stderr    '--------------'                 '--------------'     2 stderr
 13
Author: Pithikos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-13 20:42:26

Deskryptor pliku to coś więcej niż liczba. Niesie ze sobą również różne częściowo ukryte Stany (niezależnie od tego, czy jest otwarty, czy nie, do którego opisu Pliku się odnosi, a także niektóre flagi). dup powiela te informacje, dzięki czemu można np. zamknąć oba deskryptory niezależnie. Nie.

 11
Author: n.m.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-22 18:54:37

Najważniejszą rzeczą w dup () jest to, że Zwraca najmniejszą liczbę całkowitą dostępną dla nowego deskryptora pliku. To podstawa przekierowania:

int fd_redirect_to = open("file", O_CREAT);
close(1); /* stdout */
int fd_to_redirect = dup(fd_redirect_to); /* magically returns 1: stdout */
close(fd_redirect_to); /* we don't need this */

Po tym wszystko, co jest zapisane do deskryptora pliku 1 (stdout), magicznie przechodzi do "file".

 6
Author: SzG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-03 08:04:31

Załóżmy, że piszesz program powłoki i chcesz przekierować stdin i stdout w programie, który chcesz uruchomić. Może to wyglądać mniej więcej tak:

fdin = open(infile, O_RDONLY);
fdout = open(outfile, O_WRONLY);
// Check for errors, send messages to stdout.
...
int pid = fork(0);
if(pid == 0) {
    close(0);
    dup(fdin);
    close(fdin);
    close(1);
    dup(fdout);
    close(fdout);
    execvp(program, argv);
}
// Parent process cleans up, maybe waits for child.
...

Dup2() jest nieco wygodniejszym sposobem, aby to zrobić close() dup () można zastąpić przez:

dup2(fdin, 0);
dup2(fdout, 1);

Powodem, dla którego chcesz to zrobić, jest to, że chcesz zgłaszać błędy na stdout (lub stderr), więc nie możesz po prostu ich zamknąć i otworzyć nowego pliku w procesie potomnym. Po drugie, byłoby marnotrawstwem zrobić widelec, jeśli albo wywołanie open() zwróciło błąd.

 5
Author: Richard Pennington,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-22 18:51:26

Zobacz tę stronę , stdout może być aliasowany jako dup(1)...

 2
Author: Karel Frajták,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-22 18:19:19

Wystarczy wskazówka o " powielaniu standardowego wyjścia ".

Na niektórych systemach uniksowych (ale nie GNU/Linux)

fd = open("/dev/fd/1", O_WRONLY);

Jest równoważne:

fd = dup(1);
 0
Author: b3h3m0th,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-03 17:52:12

Przykład:

close(1);     //closing stdout
newfd=dup(1); //newfd takes value of least available fd number

Gdzie to się dzieje z deskryptorami plików:

0 stdin     .--------------.     0 stdin     .--------------.     0 stdin
1 stdout   =|   close(1)   :=>   2 stderr   =| newfd=dup(1) :=>   1 newfd
2 stderr    '--------------'                 '--------------'     2 stderr

Znowu pojawiło się pytanie: Jak mogę dup() deskryptor pliku, który już zamknąłem?

Wątpię, czy przeprowadziłeś powyższy eksperyment z pokazanym wynikiem, ponieważ nie byłoby to zgodne ze standardem-por. dup :

Funkcja dup () zawodzi, jeśli:

[EBADF] Argument fildes nie jest poprawnym otwartym plikiem deskryptor.

Więc po pokazanej sekwencji kodu newfd musi być nie 1, ale raczej -1, a errno EBADF.

 0
Author: Armali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-28 09:10:55