考虑这样一个场景,打开一个字符设备文件/dev/A,得到一个fd,用户态可以对这个
fd做相关的文件操作,包括ioctl, mmap, close等,内核如果保证close操作和其他
操作的同步,即不会出现close和其他文件并发执行,其他文件访问已经close掉的文件
这种情况。
内核是靠打开文件的引用计数来保证这一点的。
1 2 3 4 5 6 7
   | kernel/fs/open.c filp_open   +-> file_open_name     +-> do_filp_open       +-> path_openat         +-> alloc_empty_file 	这里在创建struct file结构的时候会把里面的f_count引用计数设置为1。
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | kernel/fs/ioctl.c ksys_ioctl系统调用   +-> fdget     +-> __fdget       在rcu锁里得到file结构的指针       +-> __fget_light         +-> __fget 	  +-> get_file_rcu_many (atomic_long_add_unless(&(x)->f_count, xx, 0))           这里只有在f_count非0的时候才会把引用计数加1。如果是0,表明已经file 	  的引用计数已经是0。__fget会去files里查fd对应的file。   +-> fdput     +-> fput       +-> fput_many         +-> atomic_long_dec_and_test(&file->f_count) 	如果减到0,在另一个内核线程中,延迟执行delay_work: 	  +-> delayed_fput_work 	    +-> delayed_fput 	      +-> __fput 	        +-> file_free(file)
   | 
 
1 2 3 4 5 6 7 8 9
   | kernel/fs/open.c close系统调用   +-> __close_fd     +-> spin_lock(&files->file_lock)     在锁里拿到fd对应的file结构的指针       +-> filp_close         +-> fput              如上     +-> spin_unlock(&files->file_lock)
   |