File descriptors From Hackepedia
A file descriptor is a handle in a program that allows data to be read and written. It is assigned a number starting at 0 and going to the file descriptor limit. A descriptor of -1 indicates an error. File descriptors are limited to files in filesystems but there is other sorts of descriptors (like sockets) that behave similarly so we bunch them together here.
When a new process is created (by means of the fork(2) system call) it inherits all open descriptors from the parent process. New descriptors are made by the following system calls open(2), pipe(2), socket(2), accept(2) and socketpair(2). A descriptor can be duplicated thus creating a new descriptor and number with the dup(2) system call. A descriptor can be destroyed by means of the close(2) system call. All programs executed from a shell have the following 3 descriptors open bound to the terminal: Stdin, Stdout and Stderr, representing descriptor numbers 0, 1 and 2 respectively. More about descriptors can be found in the fd manual page on the OpenBSD system; "man 4 fd" to see this.
Careful plumbing done by a program (such as a user shell) can use the pipe(2), fork(2), exec(2) and dup2(2) syscalls to connect the stdout of one program with stdin of another program this is called piping (see pipe). Long pipe chains (proper: pipelines) can be created this way.
When a program becomes a daemon stdin, stdout and stderr are usually closed and attached to the null device since they don't have a controlling terminal anymore. All writes to these descriptors will be discarded.
With descriptors control messaging can be used to talk to the kernel directly without having to write to it. Interfaces for this include fcntl(2), ioctl(2) and tcsetattr(2). With fcntl one can manipulate the close-on-exec flag which is useful with setuid programs.
Descriptors can be polled without having to use them in order to find out that one is ready for i/o. There are two methods to do this: poll(2) and select(2).
Descriptors can be set non-blocking meaning that a read will not block until data arrives when there is no data available. Instead if a block condition exists the syscall returns immediately and sets the errno to EWOULDBLOCK.
Instead of being inherited by from a parent by means of the fork(2) syscall a descriptor can be passed from one process to another. The means to do this is through a UNIX domain socket. One process that uses this technique is sshd.
Below you'll find a list of descriptors of different types as well as examples what to do with the information given by fstat (this example uses fstat from OpenBSD):
In fstat a filedescriptor on a file looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ bituser python2.3 5233 26 /usr 9050558 -rw-r--r-- rw 48758784 ... $ find /usr/home/bituser -inum 9050558 -print 2>/dev/null /usr/home/bituser/downloads/trusted-computing/TrustedComputing_LAFKON_HIGH.mov An Internet socket that's listening looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ root sshd 3641 5* internet stream tcp 0xfffffe800f551008 *:22 ... $ netstat -naA | head -2 Active Internet connections (including servers) PCB Proto Recv-Q Send-Q Local Address Foreign Address (state) $ netstat -naA | awk '$1 == "0xfffffe800f551008" { print }' 0xfffffe800f551008 tcp 0 0 *.22 *.* LISTEN A connected Internet socket descriptor looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ bituser python2.3 5233 27* internet stream tcp 0xfffffe801be04d18 85.75.59.86:6884 <-- 80.177.208.19:12362 A UNIX domain socket looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug ssh-agent 12530 4* unix stream 0xffff800001d80800 A UNIX domain socketpair looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ root ntpd 12284 3* unix stream 0xffff800001cd6480 <-> 0xffff800001cd6700 A desriptor to a pipe looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug fstat 26338 1 pipe 0xfffffe801f525d28 state: A descriptor on a fifo looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug sh 3840 3 /tmp 5 prw-r--r-- r 0:0 A revoke(2)'ed descriptor looks like this: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug xterm 15604 5 - - none -In Linux you'd use lsof to dig through the /proc filesystem to see open descriptors / ports. Specifically, you want to look in the /proc/
jbecker@aubrey /space/winders $ ls -l /proc/9383/fd total 6 lr-x------ 1 jbecker users 64 Oct 15 09:53 0 -> /dev/null l-wx------ 1 jbecker users 64 Oct 15 09:53 1 -> /home/jbecker/.xsession-errors l-wx------ 1 jbecker users 64 Oct 15 09:53 2 -> /home/jbecker/.xsession-errors l-wx------ 1 jbecker users 64 Oct 15 09:53 3 -> /home/jbecker/.fluxbox/log lrwx------ 1 jbecker users 64 Oct 15 09:53 4 -> socket:[2995011] lrwx------ 1 jbecker users 64 Oct 15 09:53 5 -> /dev/ptmx
German - von Hackepedia
Ein Dateien Deskriptor (engl. file descriptor) ist ein Handle in einem Programm das Daten liest und schreibt. Es wird eine nummer gegeben von null (0) bis zum Dateien Descriptor höchstwert. Ein Deskripter mit dem wert von -1 ist ein fehler. Dateien Deskriptoren sind eingeschränkt zu Dateien im Dateisystem, aber es gibt andere Deskriptoren (wie Sockets) die ähnlich funktionieren, so dass wir sie mitbeachten.
Vorsichtige Klempnerarbeit eines Programms, kann pipe(2), fork(2), exec(2) und dup2(2) System aufrufe benutzen um Stdout des einen Programms mit dem Stdin des anderen Programms zu verknüpfen. Dies ist bekannt als "piping", siehe pipe. Lange pipe "ketten" oder auch "pipelines" genannt können so benutzt werden.
Wenn ein Programm zum daemon wird, werden Stdin, Stdout, Stderr meistens geschlossen und neu an /dev/null befestigt, weil sie kein kontrollierbares TTY mehr haben. Alle beschreibungen zu diesen Deskriptoren werden so weg-geworfen.
Mit Deskriptoren kann man auch "control messaging" machen um mit dem Kernel zu reden. Die Schnittstellen hierzu sind zum beispiel fcntl(2), ioctl(2) und tcsetattr(2). Mit fcntl can man die close-on-exec flagge manipulieren was sehr benutzbar für setuid Programme ist.
Descriptoren können befragt werden ohne das man von ihnen liest oder schreibt das sie bereit sind zur E/A(IO). Es gibt zwei methoden dazu: poll(2) und select(2).
Deskriptoren können zu einem nicht-blockierbaren (non-blocking) zustand gesetzt werden so das sie nicht blockieren wenn keine neue Daten erhältlich sind. Anstatt when eine Block kondition existiert wird der system aufruf sofort beendet und die errno wird zu EWOULDBLOCK gesetzt.
Anstatt das ein Deskriptor von dem parent Prozess geerbt wird durch den fork(2) System Aufruf kann ein Deskriptor von einem Prozess zu einem anderen nicht-verwanten Prozess "geworfen" (descriptor-passing) werden. Es wird gemacht durch einen UNIX domain Socket. Ein Programm die diese technik benutzt ist sshd.
Es sind mehrere wege möglich in einem Programm die offen Dateien Deskriptoren extern zu lesen. In BSD der fstat(1) Kommando zeigt alle Programme und ihre offenen Deskriptoren an, aber nicht nur das, sonder auch was für Deskriptoren es sind (file, socket, pipe, etc). Es gibt auch einen tip wohin gerade gelesen oder geschrieben wird. Im OpenBSD system werden Netzwerk Sockets die port nummern anzeigen was sehr nützlich ist einen Dienst zu identifizieren.
Unten werden Sie eine Liste der offenen Deskriptoren von verschiedenen Typs sehen und auch Beispiele was man mit den Informationen tun kann. (Dieses Beispiel benutzt fstat von OpenBSD):
In fstat(1) ein offenen Dateiendeskriptor sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ bituser python2.3 5233 26 /usr 9050558 -rw-r--r-- rw 48758784 ... $ find /usr/home/bituser -inum 9050558 -print 2>/dev/null /usr/home/bituser/downloads/trusted-computing/TrustedComputing_LAFKON_HIGH.mov Ein Internet Socket das Horcht (LISTEN zustand) sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ root sshd 3641 5* internet strea m tcp 0xfffffe800f551008 *:22 ... $ netstat -naA | head -2 Active Internet connections (including servers) PCB Proto Recv-Q Send-Q Local Address Foreign Address (state) $ netstat -naA | awk '$1 == "0xfffffe800f551008" { pr int }' 0xfffffe800f551008 tcp 0 0 *.22 *.* LISTEN Eine Verbundener Internet Socket Deskriptor sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ bituser python2.3 5233 27* internet stream tcp 0xfffffe801be04d18 85.75.59.86:6884 <-- 80.177.208.19:12362 Ein UNIX domain Socket sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug ssh-agent 12530 4* unix stream 0xffff800001d80800 Ein UNIX domain socketpair(2) sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ root ntpd 12284 3* unix stream 0xffff800001cd6480 <-> 0xffff800001cd6700 Ein Deskriptor zu einer pipe(2) sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug fstat 26338 1 pipe 0xfffffe801f525d28 state: Ein Deskriptor auf einem FIFO (named pipe) sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug sh 3840 3 /tmp 5 prw-r--r-- r 0:0 Ein revoke(2) (also abgeschnittener) Deskriptor sieht so aus: USER CMD PID FD MOUNT INUM MODE R/W DV|SZ pbug xterm 15604 5 - - none -
In Linux würde man "lsof" benutzen um durch das /proc Dateisystem zu suchen um offene Deskriptoren zu sehen. Spezifisch würde es das /proc/PID/fd Verzeichnis durchsuchen. Jeder Symlink darin zeigt zu einer offener Datei/ Socket/etc. Ein Beispiel eines xterms:
jbecker@aubrey /space/winders $ ls -l /proc/9383/fd total 6 lr-x------ 1 jbecker users 64 Oct 15 09:53 0 -> /dev/null l-wx------ 1 jbecker users 64 Oct 15 09:53 1 -> /home/jbecker/.xsession-errors l-wx------ 1 jbecker users 64 Oct 15 09:53 2 -> /home/jbecker/.xsession-errors l-wx------ 1 jbecker users 64 Oct 15 09:53 3 -> /home/jbecker/.fluxbox/log lrwx------ 1 jbecker users 64 Oct 15 09:53 4 -> socket:[2995011] lrwx------ 1 jbecker users 64 Oct 15 09:53 5 -> /dev/ptmx
| Deutsch | English |
| Deskriptor | descriptor |
| Sockel | socket |
| Prozess | process |