Linux嵌入式驱动开发13——ioctl接口(gpio控制使用)

文章目录

全系列传送门

Linux嵌入式驱动开发01——第一个驱动Hello World(附源码)

Linux嵌入式驱动开发02——驱动编译到内核

Linux嵌入式驱动开发03——杂项设备驱动(附源码)

Linux嵌入式驱动开发04——应用层和内核层数据传输

Linux嵌入式驱动开发05——物理地址到虚拟地址映射

Linux嵌入式驱动开发06——第一个相对完整的驱动实践编写

Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)

Linux嵌入式驱动开发08——字符设备(步步为营)

Linux嵌入式驱动开发09——平台总线详解及实战

Linux嵌入式驱动开发10——设备树开发详解

Linux嵌入式驱动开发11——平台总线模型修改为设备树实例

Linux嵌入式驱动开发12——pinctl和gpio子系统实践操作

Linux嵌入式驱动开发13——ioctl接口(gpio控制使用)

Linux嵌入式驱动开发14——中断的原理以及按键中断的实现(tasklet中断下文)

Linux嵌入式驱动开发15——等待队列和工作队列

Linux嵌入式驱动开发16——按键消抖实验(内核定时器)

Linux嵌入式驱动开发17——输入子系统

Linux嵌入式驱动开发18——I2C通信

引言

我们从平台总线模型,然后到pinctrl和gpio子系统,会发现步骤逐渐的规范,代码也逐渐的简单,也越来越能体会到linux屏蔽底层硬件的优势。

在之前的代码中,在write函数中往内核中写入数据。
在这里插入图片描述
并且在应用层传入内核层的过程,需要执行copy函数,对于我们这里只需要传入0或者1的少量数据来说,有些繁琐。

什么是unlocked_ioctl接口?

unlocked_ioctl就是ioctl接口,但是功能和对应的系统调用均没有发生变化

unlocked_ioctl和read/write函数有什么相同和不同

之前我们使用read/write函数完成写数据或者读数据的操作,ioctl函数也可以往内核中写入命令。

不同点是read/write函数是两个单独的函数,完成单一的读或者写功能,我们的ioctl函数,既可以读,也可以写。

不过read/write函数在读写大数据时候效率比较高。

所以,对于gpio控制led灯或者蜂鸣器等操作时,我们不需要大量的数据读写,可以使用ioctl函数,来简化,而read/write函数专职于大量数据的传输。

unlocked_ioctl接口命令规则

unlocked_ioctl总共32位

第一个分区 0-7,命令的编号,范围是0-255

第二个分区 8-15 命令的幻数。

(第一个分区和第二个分区主要作用就是用来区分命令的。)

第三个分区 16-29 表示传递的数据大小

第四个分区 30-31 代表读写的方向
00:表示用户程序和驱动数据没有数据传递
10:表示用户程序从驱动里面读取数据
01:表示用户程序向驱动里面写入数据

11:先写数据到驱动,然后再从驱动把数据读出来(不常用)

命令的合成宏与分解宏

合成宏

在这里插入图片描述

分解宏

在这里插入图片描述

测试程序

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

#include <sys/ioctl.h>

#define CMD_TEST0 _IO(‘L’, 0) // 'L’是幻数 0是编号
#define CMD_TEST1 _IO(‘L’, 1)
#define CMD_TEST2 _IOW(‘L’, 2, int) // 第三个参数size,不是数据大小,而是数据类型,这里是四个字节的话,就是int
#define CMD_TEST3 _IOR(‘L’, 3, int) // 这四个命令幻数虽然一样,但是编号不同,所以不同。

int main(int argc, char *argv[])
{
printf(“30-31 is %d\n”, _IOC_DIR(CMD_TEST0));
printf(“30-31 is %d\n”, _IOC_DIR(CMD_TEST3));

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

我们先来测试一下代码的功能,这里使用_IOC_DIR分解命令的方向,CMD_TEST0是定义命令编号,没有数据操作,所以_IOC_DIR分解后30-31的数据应该是00

CMD_TEST3是_IOR(‘L’, 3, int),是读取,所以分解后应该读到是读对应的10,对应十进制也就是2
在这里插入图片描述
接下来继续测试_IOC_TYPE函数

    printf("8-15 is %c\n", _IOC_TYPE(CMD_TEST0));
    printf("8-15 is %c\n", _IOC_TYPE(CMD_TEST1));

执行后可以看到返回了8-15位的幻数
在这里插入图片描述

printf("编号 0-7 is %d\n", _IOC_NR(CMD_TEST2));

在这里插入图片描述

使用_IO

模拟一个闪灯的操作

module_leds.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>

#define CMD_TEST0 _IO(‘L’, 0) // 'L’是幻数 0是编号
#define CMD_TEST1 _IO(‘L’, 1)

int misc_open (struct inode inode, struct file file){

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"hello misc_open!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

int misc_release(struct inode inode, struct file file){

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"bye bye misc_release!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

ssize_t misc_read(struct file file, const char __user ubuf, size_t size, loff_t *loff_t){

<span class="token keyword">char</span> kbuf<span class="token punctuation">[</span><span class="token number">64</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"copy to user!!!\n"</span><span class="token punctuation">;</span>

<span class="token keyword">if</span><span class="token punctuation">(</span> <span class="token function">copy_to_user</span><span class="token punctuation">(</span>ubuf<span class="token punctuation">,</span> kbuf<span class="token punctuation">,</span> size<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span> <span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"copy_to_user error!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"hello misc_read!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

ssize_t misc_write(struct file file, const char __user ubuf, size_t size, loff_t *loff_t){

<span class="token keyword">char</span> kbuf<span class="token punctuation">[</span><span class="token number">64</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"copy from user!!!\n"</span><span class="token punctuation">;</span>
<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"hello misc_write!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span> <span class="token function">copy_from_user</span><span class="token punctuation">(</span>kbuf<span class="token punctuation">,</span> ubuf<span class="token punctuation">,</span> size<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span> <span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"copy_from_user error!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"buf is:%s\n"</span><span class="token punctuation">,</span> kbuf<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

long misc_ioctl(struct file *file, unsigned int cmd, unsigned long value)
{
switch (cmd)
{
case CMD_TEST0:
printk(“LED_ON!!!\n”);
case CMD_TEST1:
printk(“LED_OFF!!!\n”);
break;

<span class="token keyword">default</span><span class="token punctuation">:</span>
    <span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

struct file_operations misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_release,
.read = misc_read,
.write = misc_write,
.unlocked_ioctl = misc_ioctl,
};

struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = “hello_misc”,
.fops = &misc_fops
};

static int misc_init(void)
{
int ret;

ret <span class="token operator">=</span> <span class="token function">misc_register</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>misc_dev<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">if</span><span class="token punctuation">(</span>ret <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"misc_register failed!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"misc_register succeed!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>           <span class="token comment">// 在内核中无法使用c语言库,所以不用printf</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

static void misc_exit(void)
{
misc_deregister(&misc_dev);

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"misc exit!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

module_init(misc_init);
module_exit(misc_exit);

MODULE_LICENSE(“GPL”); //声明模块拥有开源许可

Makefile

# 开发板Linux内核的实际路径 
# KDIR变量
KDIR:=/work/linux-4.1.15

获取当前目录

PWD:=$(shell pwd)

# obj-m表示将 chrdevbase.c这个文件 编译为 chrdevbase.ko模块。
obj-m += module_leds.o

编译成模块

all:
make -C < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > K D I R < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ) < / s p a n > M < s p a n c l a s s = " t o k e n o p e r a t o r " > = < / s p a n > <span class="token punctuation">(</span>KDIR<span class="token punctuation">)</span> M<span class="token operator">=</span> <spanclass="tokenpunctuation">(</span>KDIR<spanclass="tokenpunctuation">)</span>M<spanclass="tokenoperator">=</span>(PWD) modules

clean:
make -C < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > K D I R < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ) < / s p a n > M < s p a n c l a s s = " t o k e n o p e r a t o r " > = < / s p a n > <span class="token punctuation">(</span>KDIR<span class="token punctuation">)</span> M<span class="token operator">=</span> <spanclass="tokenpunctuation">(</span>KDIR<spanclass="tokenpunctuation">)</span>M<spanclass="tokenoperator">=</span>(PWD) clean

app.c

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

#include <sys/ioctl.h>

#define CMD_TEST0 _IO(‘L’, 0) // 'L’是幻数 0是编号
#define CMD_TEST1 _IO(‘L’, 1)

int main(int argc, char *argv[])
{
int fd;

<span class="token keyword">char</span> buff<span class="token punctuation">[</span><span class="token number">64</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span><span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">;</span>

fd <span class="token operator">=</span> <span class="token function">open</span><span class="token punctuation">(</span><span class="token string">"/dev/hello_misc"</span><span class="token punctuation">,</span> O_RDWR<span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token comment">// 打开节点时候触发open函数</span>

<span class="token keyword">if</span><span class="token punctuation">(</span>fd <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>

    <span class="token function">perror</span><span class="token punctuation">(</span><span class="token string">"open error\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                 <span class="token comment">// perror在应用中打印</span>
    <span class="token keyword">return</span> fd<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">ioctl</span><span class="token punctuation">(</span>fd<span class="token punctuation">,</span> CMD_TEST0<span class="token punctuation">)</span><span class="token punctuation">;</span>                   <span class="token comment">// 触发驱动中的.unlocked_ioctl</span>
    <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">ioctl</span><span class="token punctuation">(</span>fd<span class="token punctuation">,</span> CMD_TEST1<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

结果

在测试结果中可以看到每次ioctl都会进入到驱动中的misc_ioctl中进行判断,然后打印出来预期的结果
在这里插入图片描述

使用_IOW

这里只修改了两个地方的代码
module_leds.c

long misc_ioctl(struct file *file, unsigned int cmd, unsigned long value)
{
    switch (cmd)
    {
    case CMD_TEST2:
        printk("LED_ON!!!\n");
        printk("value is %d\n", value);
        break;
    case CMD_TEST3:
        printk("LED_OFF!!!\n");
        printk("value is %d\n", value);
        break;
<span class="token keyword">default</span><span class="token punctuation">:</span>
    <span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

app.c

    while(1){
        ioctl(fd, CMD_TEST2, 0);                   // 触发驱动中的.unlocked_ioctl
        sleep(2);                               // 每隔两秒钟
        ioctl(fd, CMD_TEST3, 1);
        sleep(2);
    }

这里的一一对应的关系如图所示
在这里插入图片描述
这样,我们的实验结果就是,可以正常的写入数据
在这里插入图片描述

使用_IOR

有些时候我们需要读取按键的值,或者引脚的状态,使用_IOR就会很方便

在应用函数里,设置如下,传入value的地址到ioctl函数

    while(1){
        ioctl(fd, CMD_TEST4, &value);                   // 触发驱动中的.unlocked_ioctl
        printf("app value is %d\n", value);
        sleep(2);                               // 每隔两秒钟
<span class="token punctuation">}</span>

在驱动函数中,依然要使用copy_to_user函数,复制数据从底层到应用层中,所以,在这里第一个参数就是应用层的value的地址,因为是int型指针,所以要强制转换一下,然后第二个参数就是底层的val值,第三个就是底层val的长度大小

    case CMD_TEST4:
        val = 12;
        if( copy_to_user((int *)value, &val, sizeof(val)) != 0 ){
            printk("copy_to_user error!!!\n");
            return -1;
        }
        break;

实验结果

在这里插入图片描述
我们程序中的val可以替换为底层io口的状态。

完整代码

module_leds.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>

#define CMD_TEST0 _IO(‘L’, 0) // 'L’是幻数 0是编号
#define CMD_TEST1 _IO(‘L’, 1)

#define CMD_TEST2 _IOW(‘L’, 2, int)
#define CMD_TEST3 _IOW(‘L’, 3, int)

#define CMD_TEST4 _IOR(‘L’, 4, int)

int misc_open (struct inode inode, struct file file){

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"hello misc_open!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

int misc_release(struct inode inode, struct file file){

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"bye bye misc_release!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

ssize_t misc_read(struct file file, const char __user ubuf, size_t size, loff_t *loff_t){

<span class="token keyword">char</span> kbuf<span class="token punctuation">[</span><span class="token number">64</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"copy to user!!!\n"</span><span class="token punctuation">;</span>

<span class="token keyword">if</span><span class="token punctuation">(</span> <span class="token function">copy_to_user</span><span class="token punctuation">(</span>ubuf<span class="token punctuation">,</span> kbuf<span class="token punctuation">,</span> size<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span> <span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"copy_to_user error!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"hello misc_read!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

ssize_t misc_write(struct file file, const char __user ubuf, size_t size, loff_t *loff_t){

<span class="token keyword">char</span> kbuf<span class="token punctuation">[</span><span class="token number">64</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"copy from user!!!\n"</span><span class="token punctuation">;</span>
<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"hello misc_write!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span> <span class="token function">copy_from_user</span><span class="token punctuation">(</span>kbuf<span class="token punctuation">,</span> ubuf<span class="token punctuation">,</span> size<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span> <span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"copy_from_user error!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"buf is:%s\n"</span><span class="token punctuation">,</span> kbuf<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

long misc_ioctl(struct file file, unsigned int cmd, unsigned long value)
{
int val;
switch (cmd)
{
case CMD_TEST2:
printk(“LED_ON!!!\n”);
printk(“value is %d\n”, value);
break;
case CMD_TEST3:
printk(“LED_OFF!!!\n”);
printk(“value is %d\n”, value);
break;
case CMD_TEST4:
val = 12;
if( copy_to_user((int )value, &val, sizeof(val)) != 0 ){
printk(“copy_to_user error!!!\n”);
return -1;
}
break;

<span class="token keyword">default</span><span class="token punctuation">:</span>
    <span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

struct file_operations misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_release,
.read = misc_read,
.write = misc_write,
.unlocked_ioctl = misc_ioctl,
};

struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = “hello_misc”,
.fops = &misc_fops
};

static int misc_init(void)
{
int ret;

ret <span class="token operator">=</span> <span class="token function">misc_register</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>misc_dev<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">if</span><span class="token punctuation">(</span>ret <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"misc_register failed!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"misc_register succeed!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>           <span class="token comment">// 在内核中无法使用c语言库,所以不用printf</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

static void misc_exit(void)
{
misc_deregister(&misc_dev);

<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"misc exit!!!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

module_init(misc_init);
module_exit(misc_exit);

MODULE_LICENSE(“GPL”); //声明模块拥有开源许可

app.c

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

#include <sys/ioctl.h>

#define CMD_TEST0 _IO(‘L’, 0) // 'L’是幻数 0是编号
#define CMD_TEST1 _IO(‘L’, 1)

#define CMD_TEST2 _IOW(‘L’, 2, int)
#define CMD_TEST3 _IOW(‘L’, 3, int)

#define CMD_TEST4 _IOR(‘L’, 4, int)

int main(int argc, char *argv[])
{
int fd;

<span class="token keyword">int</span> value<span class="token punctuation">;</span>

fd <span class="token operator">=</span> <span class="token function">open</span><span class="token punctuation">(</span><span class="token string">"/dev/hello_misc"</span><span class="token punctuation">,</span> O_RDWR<span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token comment">// 打开节点时候触发open函数</span>

<span class="token keyword">if</span><span class="token punctuation">(</span>fd <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>

    <span class="token function">perror</span><span class="token punctuation">(</span><span class="token string">"open error\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                 <span class="token comment">// perror在应用中打印</span>
    <span class="token keyword">return</span> fd<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token function">ioctl</span><span class="token punctuation">(</span>fd<span class="token punctuation">,</span> CMD_TEST4<span class="token punctuation">,</span> <span class="token operator">&amp;</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>                   <span class="token comment">// 触发驱动中的.unlocked_ioctl</span>
    <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"app value is %d\n"</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                               <span class="token comment">// 每隔两秒钟</span>

<span class="token punctuation">}</span>

<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

            </div>
            <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/markdown_views-22a2fefd3b.css" rel="stylesheet">
            <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/style-4f8fbf9108.css" rel="stylesheet">
    </div>
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值