当函数a从执行点调用时,它是对地址指向函数A的JMP语句PC加载称为函数A的地址并继续。
要回到函数调用后的执行点,该功能块应具有相等的推动,并弹出堆栈。通常,在退出功能时,定义的堆栈变量被破坏(我认为这意味着从堆栈中弹出(,但是我决定在函数内定义文件描述符变量。代码如下:
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;
}
}
在运行此程序并检查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((堆栈的一部分,则文件描述符位于过程内存中?
变量 int fd;
仅从函数 func_call()
可见,在执行此功能后,它将被弹出堆栈,并且可能会覆盖内存时输入新功能。您销毁指向文件的一些int
值的事实并不意味着您关闭所述文件。如果您做了类似的事情:
int global_fd;
void foo() {
int local_fd = open("bar.txt", O_RDONLY);
global_fd = local_fd;
}
并称为foo()
?您是否期望无法再使用global_fd
Afteer foo
退出?
在这种情况下,将文件描述符视为指针,您要求内核给您文件,并且为您提供了一个可以用作此特定文件的令牌的值,此令牌是您用来让内核知道在哪个文件的函数(例如read
或lseek
ACT(的功能。当将令牌传递或破坏时,文件保持打开存储文件描述符的内核中的表。因此,当您打开文件时,您在该表中创建了一个条目。如果您不关闭文件(及其描述符(,则条目永远不会删除(这并不意味着您无法再次打开文件(。
如果文件描述符是func_call((堆栈的一部分,那么尽管尚未弹出,代码如何返回其前功能调用执行点?同样在这种情况下,为什么在函数调用后会持续存在?
据我所知,每个过程只有一个堆栈,而不是每个功能。因此,fp
变量存储在该过程的堆栈中,并在功能结束时从那里删除。
文件描述符很特别。如您所知,它们只是Int。但是它们"包含"有关正在读取的文件的大量信息(文件在磁盘上的位置,读/写指针的FIE中的位置等(,那么存储的信息在哪里?答案是它存储在OS内核中。它存储在OS内核中,因为它是为您管理文件I/O的内核工作。当我们说涉及打开文件的int是"文件描述符"时,我们的意思是,int是指存储在其他地方的信息,有点像指针。这个词"描述符"很重要。有时用于这种情况的另一个单词是" hander"。
您知道,局部变量的内存通常存储在堆栈上。当您从函数返回时,释放函数本地变量的内存非常简单 - 它们基本上与函数的堆栈帧一起消失。当它们消失时,它们确实消失了:(在C中(没有办法与他们的消失有关。特别是,对于恰好是文件描述符的变量,无法对close()
进行调用。
(如果您想在变量消失时进行清理操作,一种方法是使用C ,使用类变量,并定义一个显式 destructor 。(
当您致电malloc
时会出现类似的情况。在此功能中:
void f()
{
char *p = malloc(10);
}
我们调用malloc
分配10个字节的内存,并将返回的指针存储在本地指针变量p
中,当功能f
返回时,该指针会消失。因此,我们将指向分配的内存的指针丢失了,但是没有呼吁free()
,因此存储器仍然分配。(这是内存泄漏的示例。(