Linux eventfd分析

https://www.cnblogs.com/ck1020/p/7214310.html

每个任务都有一个文件描述符表。此文件描述符表由文件描述符编号索引,并包含有关每个打开文件的信息(文件描述)。 与内核中的许多其他对象一样,文件描述也是引用计数的。这意味着当内核的某些部分想要访问文件描述时,它必须采用引用,执行它需要做的任何事情,并释放引用。当引用计数降为零时,可以释放该对象。对于文件描述,open()递增引用计数,close()递减它,因此文件描述在打开和/或内核使用时无法释放(例如:想象一个过程中的一个线程close()一个文件,而另一个线程仍然是read()ing文件:文件描述在读取fput()s之前实际上不会被释放。 要从文件描述符获取对文件描述的引用,内核具有fget()函数,fput()将释放该引用。由于多个线程可能在不同的CPU上同时访问相同的文件描述,因此fget()和fput()必须使用适当的锁定。在现代,他们使用RCU;仅仅是文件描述符表的读者不会/几乎没有成本。 但是RCU还不够优化。考虑到拥有非多线程的进程是很常见的。在这种情况下,您不必担心访问相同文件描述的同一进程中的其他线程。访问我们的文件描述符表的唯一任务是我们。因此,作为优化,当当前文件描述符表仅用于单个任务时,fget_light() / fput_light()不会触及引用计数。

struct file *fget_light(unsigned int fd, int *fput_needed)
{
struct file file;
/
The file descriptor table for our current task */
struct files_struct files = current->files;
/
Assume we won’t need to touch the reference count,
* since the count won’t reach zero (we are not close(),
* and hope we don’t run concurrently to close()),
* fput_light() won’t actually need to fput().
*/
fput_needed = 0;
/
Check whether we are actually the only task with access to the fd table /
if (likely((atomic_read(&files->count) == 1))) {
/
Yep, get the reference to the file description /
file = fcheck_files(files, fd);
} else {
/
Nope, we’ll need some locking /
rcu_read_lock();
/
Get the reference to the file description /
file = fcheck_files(files, fd);
if (file) {
/
Increment the reference count /
if (atomic_long_inc_not_zero(&file->f_count))
/
fput_light() will actually need to fput() */
fput_needed = 1;
else
/
Didn’t get the reference, someone’s freed /
/
Happens if the file was close()d and all the
* other accessors ended its work and fput().
*/
file = NULL;
}
rcu_read_unlock();
}
return file;
}

猜你喜欢

转载自blog.csdn.net/runshui27/article/details/120594145