When a function A is called from a point of execution, internally it is a JMP statement to the address pointing to function A. So the current point of execution is saved onto the stack, the PC loads the address of the called function A and continues.
To get back to the point of execution after the function call, the function block should have equal push and pops onto the stack. Normally in C on exiting the function, the stack variables defined are destroyed(which I presume means popped off the stack), but I decided to define a file descriptor variable inside my function. The code is below:
void main() { printf("In the beginning there was main()n"); func_call(); printf("func_call completen"); while(1); } void func_call() { int fp; //Opening a file to get handle to it. fp = open("stack_flush.c", O_RDONLY); if (fp < 0 ) { perror("fp could not open stack_flush.c"); return; } }
On running this program and checking lsof, I can see that the fd is still open upon exiting the function func_call().
stack_flu 3791 vvdnlt260 0u CHR 136,1 0t0 4 /dev/pts/1 stack_flu 3791 vvdnlt260 1u CHR 136,1 0t0 4 /dev/pts/1 stack_flu 3791 vvdnlt260 2u CHR 136,1 0t0 4 /dev/pts/1 stack_flu 3791 vvdnlt260 3r REG 8,3 526 24660187 /home/vvdnlt260/Nishanth/test_space/stack_flush.c
I checked the wikipedia entry for file descriptors and I found this:
To perform input or output, the process passes the file descriptor to the kernel through a system call, and the kernel will access the file on behalf of the process. The process does not have direct access to the file or inode tables.
From the above statement it’s obvious that the file descriptor integer value is stored in process memory, but although it was defined in a function, the file descriptor was not local to the function as it did not get removed on function exit.
So my question is 2 fold:
1) If the file descriptor is part of the func_call() stack, then how does the code return to its pre function call execution point although it has not been popped off? Also in this case why does it persist after the function call exists?
2) If not part of the func_call() stack where does the file descriptor reside in the process memory?
Advertisement
Answer
The variable int fd;
is only visible from the function func_call()
and after this function finishes executing it will be popped of the stack and the memory will be overwritten probably when a new function is entered. The fact that you destroy some int
value pointing to the file does not mean that you close said file. What if you did something like:
int global_fd; void foo() { int local_fd = open("bar.txt", O_RDONLY); global_fd = local_fd; }
And called foo()
? Would You expect to not be able to use global_fd
anymore afteer foo
exits?
It is helpful to think in this case of the file descriptor as a of a pointer, You ask the kernel to give You the file, and it gives you a value that You can use as a token for this specific file, this token is what you use to let the kernel know on which file should the function like read
or lseek
act. When the token is passed around or destroyed the file remains open just as destroying the pointer does not free the allocated memory.