gpt4 book ai didi

linux - 如何获取 Linux 驱动级别的引用计数?

转载 作者:太空宇宙 更新时间:2023-11-04 09:33:17 26 4
gpt4 key购买 nike

在Linux 内核中,打开的文件由struct file 指示,文件描述符表包含一个指向struct file 的指针。 f_count 是结构文件中的重要成员。 f_count,表示引用计数。系统调用 dup()fork() 使其他文件描述符指向相同的 struct file

如图(抱歉,我声望太低,图片上传不了),fd1fd2指向struct文件,因此引用计数等于 2,因此 f_count = 2

我的问题是如何通过编程获取f_count的值。

更新:好的,为了让自己更清楚,我将展示我的代码,包括字符设备驱动程序、Makefile 和我的应用程序。:D

设备驱动.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

应用程序.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的(char device file)f_count?是否可以通过printk获取?

最佳答案

您应该将引用计数器从其他模块和用户空间应用程序划分到模块。 lsmod 显示有多少模块使用了您的模块。

sctp                  247143  4 
libcrc32c 12644 1 sctp

没有 libcrc32c 就不可能加载 sctp 因为 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).

如果需要手动修改模块的计数器使用:

int try_module_get(struct module* module);
void module_put(struct module* module);

如果模块卸载,它将返回 false。您还可以浏览所有模块。通过列表链接的模块。

在内核中打开文件是个坏主意。在内核中,您可以访问 inode。尝试阅读 dupfork 的手册页。在您的系统中,您可以研究 lsof 工具。

关于linux - 如何获取 Linux 驱动级别的引用计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29276400/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com