Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am trying to get the whole picture with file descriptors. Say I have process1 which initially has these file descriptors:

 _process1_
|          |
| 0 stdin  |
| 1 stdout |
| 2 stderr |
|__________|

What really happens when, in the process, we call this function (in C):

close(1);

The file descriptor 1 translates to the stdout FILE structure in the kernel's Open Files Table.

With the code above the file descriptor 1 gets deleted from the process's table which becomes:

 _process1_
|          |
| 0 stdin  |
| 2 stderr |
|__________|

But what happens in the kernel? Does the stdout FILE structure get deallocated? How is that possible if stdout is a special file (the monitor) and probably being used by other processes? What about FILE structures that are just normal files (.txt for example)? What if such a file is being used by an other process?

share|improve this question
add comment

2 Answers

The file descriptor 1 translates to the stdout FILE structure in the Kernel's Open Files Table.

This is a misunderstanding. The kernel's file table has nothing whatsoever to do with user-space file structures.

In any event, the kernel has two levels of indirection. There is the internal structure that represents the file itself, which is reference counted. There is an "open file description" that is reference counted. And then there is the file handle, which is not reference counted. The file structure points the way to the inode itself. The open file description contains things like the open mode and file pointer.

When you call close, you always close the file handle. When a file handle is closed, the reference count on its open file description is decremented. If it goes to zero, the open file description is also released and the reference count on the file itself is decremented. Only if that goes to zero is the kernel's file structure freed.

There is no chance for one process to release a resource another process is using because shared resources are reference counted.

share|improve this answer
add comment

In this case not a lot will happen. stdin, stdout, and stderr all tend to be clones of the same file descriptor. The reference counter for the file descriptor will be decremented by one. The same file descriptor is usually held by the shell from which the program was run, so the file descriptor needs to be kept.

The kernel keeps reference counts for all files (inodes) that are open. As long as the reference count is greater than zero the file will be kept. I would expect a separate counter is kept for open file handles. Once this hits zero the kernel can release the memory used by the file handle.

When all references to the file (directory entries and file handles) have been removed, the file system code will mark the inode for reuse. Any blocks the file has are made available for allocation. Many file systems will clear the block pointers in the inode when it is released. This makes recovering a deleted file difficult. Updates to disk may be buffered and completed at a later time.

share|improve this answer
1  
Two questions: (1) are the file descriptors really ref-counted? When you control-d a cat > some.file, cat gets an EOF on stdin, but the shell does not. (2) Why reference counting? Why not some form of garbage collection? Isn't GC far better in user space? –  Bruce Ediger Nov 28 '11 at 4:54
    
Expanding on BillThor's answer: In normal cases stdin, stdout, and stderr are just open file handles to a TTY device. So if you close the file handle, that TTY device is still there, and can even be re-opened again at a later time. –  Patrick Nov 28 '11 at 5:03
1  
@BruceEdiger: (1) when the shell runs cat > some.file what its actually doing is forking, opening up 'some.file' and assigning it to file descriptor 1, then it does exec("cat"). When a process is exec()'d, it inherits the open file descriptors. –  Patrick Nov 28 '11 at 5:06
    
@BruceEdiger (2) Reference counting is a perfectly fine form of garbage collection when it's used on data structures that do not contain pointers to (or chains of pointers ending in) other data structures of the same type. Also, this is happening in kernel space (not that it matters very much). –  Gilles Nov 28 '11 at 17:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.