当前位置: 首页 > 工具软件 > 0release > 使用案例 >

linux驱动15:open和release

翟冯浩
2023-12-01

open

int (*open) (struct inode *, struct file *);
open用于驱动程序的初始化,open主要的工作:

  • 检查设备特定的错误(如设备未就绪或硬件问题)
  • 如果设备是首次打开,则进行初始化(如果维护打开计数)
  • 如有必要,更新f_op指针
  • 分配并填写置于filp->private_data里的数据

release

int (*release) (struct inode *, struct file *);
主要完成以下工作:

  • 释放由open分配的、保存在file->private_data中的数据
  • 在最后一次关闭操作时关闭设备(如果维护打开计数)

当关闭一个设备的次数比打开的次数多时,系统发送什么情况?

        并不是每个close系统调用都会引起release方法的调用。只有那些真正释放设备数据结构的close调用才会调用release方法。内核对每个file结构维护其被使用多少次的计数器。只有open创建新的数据结构,其他操作如fork、dup只是增加已有结构的计数。file结构的计数归零时,close才调用release,这只在删除这个结构时发生。close和release的关系保证了每次open只有一次release。

flush方法在应用程序每次调用close时都会被调用。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static int major = 277;
static int minor = 0;
static dev_t devnum1;
static struct cdev cdev1;

int hello_open(struct inode *pinode, struct file *pfile)
{
	printk("hello_open, minor:%d, major:%d\n", iminor(pinode), imajor(pinode));
	return 0;
}

int hello_release(struct inode *pinode, struct file *pfile)
{
	printk("hello_release, minor:%d, major:%d\n", iminor(pinode), imajor(pinode));	
	return 0;
}

static struct file_operations hello_ops = {
	.open = hello_open,
	.release = hello_release,
};

static int hello_init(void)
{
	printk("hello_init\n");
	devnum1 = MKDEV(major,minor);
	printk("major:%d, minor:%d\n", MAJOR(devnum1), MINOR(devnum1));
	if (register_chrdev_region(devnum1, 1, "hello1"))//分配设备号
	{
		printk("register_chrdev_region failed\n");
		return -1;
	}

	cdev_init(&cdev1, &hello_ops);//初始化cdev,绑定fops
	if (cdev_add(&cdev1, devnum1, 1) < 0)//添加设备到内核
	{
		printk("cdev_add failed\n");
		unregister_chrdev_region(devnum1, 1);
		return -1;
	}

	return 0;
}

static void hello_exit(void)
{
	printk("hello_exit\n");
	cdev_del(&cdev1);
	unregister_chrdev_region(devnum1, 1);
}

MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

在insmod后创建设备节点:mknod /dev/hello1 c 277 0   (mknod 节点名 c 主设备号 次设备号)

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char * argv [ ])
{
	int fd = open("/dev/hello1", O_RDWR, 666);
	if (fd < 0)
	{
		perror("open faied");
		return -1;
	}

	printf("open successed: %d\n", fd);

	sleep(2);
	close(fd);
    return 0;
}

 类似资料: