【发布时间】:2017-10-30 12:14:02
【问题描述】:
当一个函数A从一个执行点被调用时,内部是一个JMP语句到指向函数A的地址。所以当前的执行点被保存到堆栈中,PC加载被调用函数的地址A 并继续。
要在函数调用后返回执行点,函数块应该具有相等的推送和弹出堆栈。通常在 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
我检查了 wikipedia 条目中的文件描述符,发现:
为了执行输入或输出,进程通过系统调用将文件描述符传递给内核,内核将代表进程访问文件。该进程没有直接访问文件或 inode 表的权限。
从上面的语句很明显文件描述符整数值存储在进程内存中,但是虽然它是在函数中定义的,但文件描述符不是函数本地的,因为它没有在函数退出时被删除。
所以我的问题是 2 倍:
1) 如果文件描述符是 func_call() 堆栈的一部分,那么代码虽然没有被弹出,但如何返回到它的函数调用前执行点?同样在这种情况下,为什么它在函数调用存在后仍然存在?
2) 如果不是 func_call() 堆栈的一部分,文件描述符在进程内存中的位置是什么?
【问题讨论】:
-
相关,我认为
close()函数可能值得一读。 -
函数返回后,本地(自动)变量
fp将超出范围。带有元数据的实际“文件”存储在内核内部结构的表中。 “文件描述符”基本上只是该表的索引。 -
由内核存储。
标签: c linux memory-management file-descriptor