在Linux内核中,打开的文件由struct file
表示,文件描述符表包含指向struct file
的指针。 f_count
是struct文件中的重要成员。 f_count
,表示引用计数。系统调用dup()
和fork()
使其他文件描述符指向同一struct file
。
如图所示(抱歉,我的声誉太低,图片无法上传),fd1
和fd2
指向struct file
,因此引用计数为等于2,因此f_count = 2
。
我的问题是如何通过编程获得f_count
的价值。
更新:好的,为了让自己更清楚,我将展示我的代码,包括char设备驱动程序,Makefile和我的应用程序。:D
deviceDriver.c
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/fs.h"
#include "linux/init.h"
#include "linux/types.h"
#include "linux/errno.h"
#include "linux/uaccess.h"
#include "linux/kdev_t.h"
#define MAX_SIZE 1024
static int my_open(struct inode *inode, struct file *file);
static int my_release(struct inode *inode, struct file *file);
static ssize_t my_read(struct file *file, char __user *user, size_t t, loff_t *f);
static ssize_t my_write(struct file *file, const char __user *user, size_t t, loff_t *f);
static char message[MAX_SIZE] = "-------congratulations--------!";
static int device_num = 0;//device number
static int counter = 0;
static int mutex = 0;
static char* devName = "myDevice";//device name
struct file_operations pStruct =
{ open:my_open, release:my_release, read:my_read, write:my_write, };
/* regist the module */
int init_module()
{
int ret;
/ **/
ret = register_chrdev(0, devName, &pStruct);
if (ret < 0)
{
printk("regist failure!\n");
return -1;
}
else
{
printk("the device has been registered!\n");
device_num = ret;
printk("<1>the virtual device's major number %d.\n", device_num);
printk("<1>Or you can see it by using\n");
printk("<1>------more /proc/devices-------\n");
printk("<1>To talk to the driver,create a dev file with\n");
printk("<1>------'mknod /dev/myDevice c %d 0'-------\n", device_num);
printk("<1>Use \"rmmode\" to remove the module\n");
return 0;
}
}
void cleanup_module()
{
unregister_chrdev(device_num, devName);
printk("unregister it success!\n");
}
static int my_open(struct inode *inode, struct file *file)
{
if(mutex)
return -EBUSY;
mutex = 1;//lock
printk("<1>main device : %d\n", MAJOR(inode->i_rdev));
printk("<1>slave device : %d\n", MINOR(inode->i_rdev));
printk("<1>%d times to call the device\n", ++counter);
try_module_get(THIS_MODULE);
return 0;
}
/* release */
static int my_release(struct inode *inode, struct file *file)
{
printk("Device released!\n");
module_put(THIS_MODULE);
mutex = 0;//unlock
return 0;
}
static ssize_t my_read(struct file *file, char __user *user, size_t t, loff_t *f)
{
if(copy_to_user(user,message,sizeof(message)))
{
return -EFAULT;
}
return sizeof(message);
}
static ssize_t my_write(struct file *file, const char __user *user, size_t t, loff_t *f)
{
if(copy_from_user(message,user,sizeof(message)))
{
return -EFAULT;
}
return sizeof(message);
}
生成文件:
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifeq ($(KERNELRELEASE),)
# Assume the source tree is where the running kernel was built
# You should set KERNELDIR in the environment if it's elsewhere
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
# The current directory is passed to sub-makes as argument
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
.PHONY: modules modules_install clean
else
# called from kernel build system: just declare what our modules are
obj-m := devDrv.o
endif
application.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_SIZE 1024
int main(void)
{
int fd;
char buf[MAX_SIZE];
char get[MAX_SIZE];
char devName[20], dir[50] = "/dev/";
system("ls /dev/");
printf("Please input the device's name you wanna to use :");
gets(devName);
strcat(dir, devName);
fd = open(dir, O_RDWR | O_NONBLOCK);
if (fd != -1)
{
read(fd, buf, sizeof(buf));
printf("The device was inited with a string : %s\n", buf);
/* test fot writing */
printf("Please input a string :\n");
gets(get);
write(fd, get, sizeof(get));
/* test for reading */
read(fd, buf, sizeof(buf));
system("dmesg");
printf("\nThe string in the device now is : %s\n", buf);
close(fd);
return 0;
}
else
{
printf("Device open failed\n");
return -1;
}
}
有任何想法获取struct file
&#39;(字符设备文件)f_count
?它是否通过printk
的方式得到了它?
答案 0 :(得分:2)
您应该将参考计数器与其他模块和用户空间应用程序中的模块分开。 lsmod
显示有多少模块使用您的模块。
sctp 247143 4
libcrc32c 12644 1 sctp
如果没有sctp
,则无法加载libcrc32c
,因为sctp
使用libcrc32
中的导出函数来计算数据包的控制和。
引用计数器本身嵌入在模块数据结构中,可以使用函数uint module_refcount(struct module* module);
您可以使用:
printk("Module reference counter: %d\n", (int)module_refcount(THIS_MODULE));
THIS_MODULE
它是.owner
字段(struct file_operations
内)当前可加载模块(内置模块为NULL)的引用。
如果需要手动修改模块的计数器使用:
int try_module_get(struct module* module);
void module_put(struct module* module);
如果模块已卸载,则会返回false
。您也可以通过所有模块移动。通过列表链接的模块。
在内核中打开文件是个坏主意。在内核中,您可以访问inode
。尝试阅读dup
和fork
的手册页。在您的系统中,您可以调查lsof
工具。