当前位置: 技术问答>linux和unix
驱动中的open函数和应用程序中的open函数是什么关系阿?
来源: 互联网 发布时间:2017-01-22
本文导语: 在网上看见这么一个例子:http://apps.hi.baidu.com/share/detail/32585036 #include #include #include #include #include #include #include #include #include #include #include typedef unsigned char BYTE; #define DS18B20_PIN S3C2410_GPB1 #define ...
在网上看见这么一个例子:http://apps.hi.baidu.com/share/detail/32585036
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef unsigned char BYTE;
#define DS18B20_PIN S3C2410_GPB1
#define DS18B20_PIN_OUTP S3C2410_GPB1_OUTP
#define DS18B20_PIN_INP S3C2410_GPB1_INP
#define HIGH 1
#define LOW 0
#define DEV_NAME "DS18B20"
#define DEV_MAJOR 232
static BYTE data[2];
// DS18B20复位函数
BYTE DS18b20_reset (void)
{
// 配置GPIOB0输出模式
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
// 向18B20发送一个上升沿,并保持高电平状态约100微秒
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
udelay(100);
// 向18B20发送一个下降沿,并保持低电平状态约600微秒
s3c2410_gpio_setpin(DS18B20_PIN, LOW);
udelay(600);
// 向18B20发送一个上升沿,此时可释放DS18B20总线
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
udelay(100);
// 以上动作是给DS18B20一个复位脉冲
// 通过再次配置GPIOB1引脚成输入状态,可以检测到DS18B20是否复位成功
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
// 若总线在释放后总线状态为高电平,则复位失败
if(s3c2410_gpio_getpin(DS18B20_PIN)){ printk("DS18b20 reset failed.rn"); return 1;}
return 0;
}
void DS18b20_write_byte (BYTE byte)
{
BYTE i;
// 配置GPIOB1为输出模式
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
// 写“1”时隙:
// 保持总线在低电平1微秒到15微秒之间
// 然后再保持总线在高电平15微秒到60微秒之间
// 理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平
//
// 写“0”时隙:
// 保持总线在低电平15微秒到60微秒之间
// 然后再保持总线在高电平1微秒到15微秒之间
// 理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平
for (i = 0; i >= 1;
}
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
}
BYTE DS18b20_read_byte (void)
{
BYTE i = 0;
BYTE byte = 0;
// 读“1”时隙:
// 若总线状态保持在低电平状态1微秒到15微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“1”信号
// 理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平
//
// 读“0”时隙:
// 若总线状态保持在低电平状态15微秒到30微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“0”信号
// 理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平
for (i = 0; i >= 1;
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
// 若总线在我们设它为低电平之后若1微秒之内变为高
// 则认为从DS18B20处收到一个“1”信号
// 因此把byte的D7为置“1”
if (s3c2410_gpio_getpin(DS18B20_PIN)) byte |= 0x80;
udelay(60);
}
return byte;
}
void DS18b20_proc(void)
{
while(DS18b20_reset());
udelay(120);
DS18b20_write_byte(0xcc);
DS18b20_write_byte(0x44);
udelay(5);
while(DS18b20_reset());
udelay(200);
DS18b20_write_byte(0xcc);
DS18b20_write_byte(0xbe);
data[0] = DS18b20_read_byte();
data[1] = DS18b20_read_byte();
}
static ssize_t s3c2440_18b20_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
DS18b20_proc();
buf[0] = data[0];
buf[1] = data[1];
return 1;
}
static struct file_operations s3c2440_18b20_fops =
{
.owner = THIS_MODULE,
.read = s3c2440_18b20_read,
};
static int __init s3c2440_18b20_init(void)
{
if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_18b20_fops) i_cdev;
if (!p) {
inode->i_cdev = p = new;
list_add(&inode->i_devices, &p->list);
new = NULL;
} else if (!cdev_get(p))
ret = -ENXIO;
} else if (!cdev_get(p))
ret = -ENXIO;
spin_unlock(&cdev_lock);
cdev_put(new);
if (ret)
return ret;
ret = -ENXIO;
filp->f_op = fops_get(p->ops);//这个地方就是后去你自己驱动中定义的文件操作了。
if (!filp->f_op)
goto out_cdev_put;
if (filp->f_op->open) {
ret = filp->f_op->open(inode,filp); //这个函数就是你的驱动中定义的xxx_open函数了
if (ret)
goto out_cdev_put;
}
return 0;
out_cdev_put:
cdev_put(p);
return ret;
}
同时,chrdev_open后,应用程序就可以通过read,和write调用驱动中定义的xxx_read,xxx_write函数了,明白了吗。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef unsigned char BYTE;
#define DS18B20_PIN S3C2410_GPB1
#define DS18B20_PIN_OUTP S3C2410_GPB1_OUTP
#define DS18B20_PIN_INP S3C2410_GPB1_INP
#define HIGH 1
#define LOW 0
#define DEV_NAME "DS18B20"
#define DEV_MAJOR 232
static BYTE data[2];
// DS18B20复位函数
BYTE DS18b20_reset (void)
{
// 配置GPIOB0输出模式
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
// 向18B20发送一个上升沿,并保持高电平状态约100微秒
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
udelay(100);
// 向18B20发送一个下降沿,并保持低电平状态约600微秒
s3c2410_gpio_setpin(DS18B20_PIN, LOW);
udelay(600);
// 向18B20发送一个上升沿,此时可释放DS18B20总线
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
udelay(100);
// 以上动作是给DS18B20一个复位脉冲
// 通过再次配置GPIOB1引脚成输入状态,可以检测到DS18B20是否复位成功
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
// 若总线在释放后总线状态为高电平,则复位失败
if(s3c2410_gpio_getpin(DS18B20_PIN)){ printk("DS18b20 reset failed.rn"); return 1;}
return 0;
}
void DS18b20_write_byte (BYTE byte)
{
BYTE i;
// 配置GPIOB1为输出模式
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
// 写“1”时隙:
// 保持总线在低电平1微秒到15微秒之间
// 然后再保持总线在高电平15微秒到60微秒之间
// 理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平
//
// 写“0”时隙:
// 保持总线在低电平15微秒到60微秒之间
// 然后再保持总线在高电平1微秒到15微秒之间
// 理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平
for (i = 0; i >= 1;
}
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
}
BYTE DS18b20_read_byte (void)
{
BYTE i = 0;
BYTE byte = 0;
// 读“1”时隙:
// 若总线状态保持在低电平状态1微秒到15微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“1”信号
// 理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平
//
// 读“0”时隙:
// 若总线状态保持在低电平状态15微秒到30微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“0”信号
// 理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平
for (i = 0; i >= 1;
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
// 若总线在我们设它为低电平之后若1微秒之内变为高
// 则认为从DS18B20处收到一个“1”信号
// 因此把byte的D7为置“1”
if (s3c2410_gpio_getpin(DS18B20_PIN)) byte |= 0x80;
udelay(60);
}
return byte;
}
void DS18b20_proc(void)
{
while(DS18b20_reset());
udelay(120);
DS18b20_write_byte(0xcc);
DS18b20_write_byte(0x44);
udelay(5);
while(DS18b20_reset());
udelay(200);
DS18b20_write_byte(0xcc);
DS18b20_write_byte(0xbe);
data[0] = DS18b20_read_byte();
data[1] = DS18b20_read_byte();
}
static ssize_t s3c2440_18b20_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
DS18b20_proc();
buf[0] = data[0];
buf[1] = data[1];
return 1;
}
static struct file_operations s3c2440_18b20_fops =
{
.owner = THIS_MODULE,
.read = s3c2440_18b20_read,
};
static int __init s3c2440_18b20_init(void)
{
if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_18b20_fops) i_cdev;
if (!p) {
inode->i_cdev = p = new;
list_add(&inode->i_devices, &p->list);
new = NULL;
} else if (!cdev_get(p))
ret = -ENXIO;
} else if (!cdev_get(p))
ret = -ENXIO;
spin_unlock(&cdev_lock);
cdev_put(new);
if (ret)
return ret;
ret = -ENXIO;
filp->f_op = fops_get(p->ops);//这个地方就是后去你自己驱动中定义的文件操作了。
if (!filp->f_op)
goto out_cdev_put;
if (filp->f_op->open) {
ret = filp->f_op->open(inode,filp); //这个函数就是你的驱动中定义的xxx_open函数了
if (ret)
goto out_cdev_put;
}
return 0;
out_cdev_put:
cdev_put(p);
return ret;
}
同时,chrdev_open后,应用程序就可以通过read,和write调用驱动中定义的xxx_read,xxx_write函数了,明白了吗。
|
用户空间使用系统调用open时,内核会自动调用file_operations 结构体中的open函数。
其他人都已经写的很清楚了。
static struct file_operations s3c2440_18b20_fops =
{
.owner = THIS_MODULE,
.read = s3c2440_18b20_read,
};
不过,你的这个驱动并没有定义open函数。如果没有定义的话,会调用一个默认的
open函数,永远可以打开成功。
不过,建议最好写一个自己的open函数。。。。
其他人都已经写的很清楚了。
static struct file_operations s3c2440_18b20_fops =
{
.owner = THIS_MODULE,
.read = s3c2440_18b20_read,
};
不过,你的这个驱动并没有定义open函数。如果没有定义的话,会调用一个默认的
open函数,永远可以打开成功。
不过,建议最好写一个自己的open函数。。。。