Reputation: 11
In the Linux kernel the opened file is indicated by struct file
, and the file descriptor table contains a pointers which is point to struct file
. f_count
is an important member in the struct file. f_count
, which means Reference Count. The system call dup()
and fork()
make other file descriptor point to same struct file
.
As shown in the picture (sorry, my reputation is too low, the picture can not be uploaded), fd1
and fd2
point to the struct file
, so the Reference Count is equal to 2, thus f_count = 2
.
My question is how can i get the value of the f_count
by programming.
UPDATE:ok,In order to make myself more clear i will show my code, both the char device driver,Makefile and my application.: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);
}
Makefile:
# 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;
}
}
Any idea to get the struct file
's(char device file) f_count
? Is it poassible get it by the way of printk
?
Upvotes: 0
Views: 4003
Reputation: 613
You should divide reference counter to module from other module and from user-space application. lsmod
show how many modules use your module.
sctp 247143 4
libcrc32c 12644 1 sctp
It is impossible load sctp
without libcrc32c
because sctp
use exported function from libcrc32
to calculate control sum for packets.
The reference counter itself is embedded in the module data structure and can be obtained with the function uint module_refcount(struct module* module);
You can use:
printk("Module reference counter: %d\n", (int)module_refcount(THIS_MODULE));
THIS_MODULE
it is a reference to current loadable module (for build-in module it is NULL) inside .owner
field (inside struct file_operations
).
If there is a need manually modify module's counter use:
int try_module_get(struct module* module);
void module_put(struct module* module);
If module unloaded it will return false
. You also can move thru all modules. Modules linked via list.
File opening inside kernel it is bad idea. Inside kernel you can get access to inode
. Try read man pages for dup
and fork
. In you system you can investigate lsof
tools.
Upvotes: 2