int (*open) (struct inode *, struct file *);
open用于驱动程序的初始化,open主要的工作:
int (*release) (struct inode *, struct file *);
主要完成以下工作:
当关闭一个设备的次数比打开的次数多时,系统发送什么情况?
并不是每个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;
}