当从一个执行点调用函数A时,内部是JMP语句指向函数A的地址。所以当前执行点被保存到栈上,PC加载被调用函数的地址A 并继续。
要在函数调用后回到执行点,函数 block 应该有相等的压入和弹出到堆栈中。通常在 C 中退出函数时,定义的堆栈变量被销毁(我认为这意味着从堆栈中弹出),但我决定在我的函数中定义一个文件描述符变量。代码如下:
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;
}
}
在运行这个程序并检查 lsof 时,我可以看到 fd 在退出函数 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
我检查了文件描述符的维基百科条目,我发现了这个:
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.
从上面的语句可以明显看出,文件描述符整数值存储在进程内存中,但尽管它是在函数中定义的,但文件描述符不是函数本地的,因为它在函数退出时没有被删除。
所以我的问题有两个:
1) 如果文件描述符是 func_call() 栈的一部分,那么代码如何返回到它之前的函数调用执行点,虽然它还没有被弹出?同样在这种情况下,为什么它在函数调用存在后仍然存在?
2) 如果不是 func_call() 堆栈的一部分,文件描述符驻留在进程内存中的什么位置?
最佳答案
变量 int fd;
仅在函数 func_call()
中可见,在该函数执行完毕后,它将被弹出堆栈并覆盖内存可能是在输入新功能时。事实上,您销毁了一些指向该文件的 int
值并不意味着您关闭了该文件。如果你做了类似的事情会怎样:
int global_fd;
void foo() {
int local_fd = open("bar.txt", O_RDONLY);
global_fd = local_fd;
}
并调用了foo()
?您是否希望在 foo
退出后无法再使用 global_fd
?
在这种情况下,将文件描述符视为指针会很有帮助,您要求内核为您提供文件,它会为您提供一个值,您可以将其用作该特定文件的标记,这token 是你用来让内核知道像 read
或 lseek
这样的函数应该作用于哪个文件。当 token 被传递或销毁时,文件保持打开状态,就像销毁指针不会释放分配的内存一样。
关于c - 文件描述符存储在进程内存中的什么位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44255144/