where is file descriptor stored in process memory?

让人想犯罪 __ 提交于 2019-12-14 03:49:36

问题


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 complete\n");
    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?


回答1:


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.




回答2:


When you open a file there's a table in the kernel where descriptor of files are stored. So, when you opened your file, you created an entry in that table. If you don't close the file (with its descriptor) the entry is never deleted (it doesn't mean you cannot open the file again).

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?

As far as I know, there's only one stack per process, not per function. So the fp variable is stored at the stack of the process and it's deleted from there when the function ends.




回答3:


File descriptors are special. As you know, they're just ints. But they "contain" a fair amount of information about the file being read (the location of the file on disk, the position within the fie of the read/write pointer, etc.), so where is that information stored? The answer is that it's stored somewhere in the OS kernel. It's stored in the OS kernel because its the kernel's job to manage file I/O for you. When we say that the int referring to the open file is a "file descriptor" we mean that the int is referring to information stored somewhere else, sort of like a pointer. That word "descriptor" is important. Another word that's sometimes used for this sort of situation is "handle".

As you know, the memory for local variables is generally stored on the stack. When you return from a function, releasing the memory for the function's local variables is very simple -- they basically disappear along with the function's stack frame. And when they disappear, they do just disappear: there's no way (in C) to have some action associated with their disappearing. In particular, there's no way to have the effect of a call to close() for variables that happen to be file descriptors.

(If you want to have a cleanup action take place when a variable disappears, one way is to use C++, and use a class variable, and define an explicit destructor.)

A similar situation arises when you call malloc. In this function:

void f()
{
    char *p = malloc(10);
}

we call malloc to allocate 10 bytes of memory and store the returned pointer in a local pointer variable p, which disappears when function f returns. So we lose the pointer to the allocated memory, but there's no call to free(), so the memory remains allocated. (This is an example of a memory leak.)



来源:https://stackoverflow.com/questions/44255144/where-is-file-descriptor-stored-in-process-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!