43.封装驱动提供的api函数

应用工程师是不希望看到驱动的相关定义,比如#define TIMER_OPEN _IO('L',0),因此需要封装,提供相关的api函数。

timerlib.h

cpp 复制代码
#ifndef _TIMELIB_H_
#define _TIMELIB_H_
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
 
#define TIMER_OPEN _IO('L',0)
#define TIMER_CLOSE _IO('L',1)
#define TIMER_SET _IOW('L',2,int)
int dev_open();
int timer_open(int fd);
int timer_close(int fd);
int timer_set(int fd,int arg);
 
#endif

timeropen.c

cpp 复制代码
#include "timerlib.h"
int timer_open(int fd)
{
    int ret;
    ret = ioctl(fd,TIMER_OPEN);
    if(ret < 0){
        printf("ioctl open error \n");
        return -1;
    }
    return ret;
}

timerclose.c

cpp 复制代码
#include "timerlib.h"
int timer_close(int fd)
{
    int ret;
    ret = ioctl(fd,TIMER_CLOSE);
    if(ret < 0){
        printf("ioctl  close error \n");
        return -1;
    }
    return ret;
}

timerset.c

cpp 复制代码
#include "timerlib.h"
int timer_set(int fd,int arg)
{
    int ret;
    ret = ioctl(fd,TIMER_SET,arg);
    if(ret < 0){
        printf("ioctl error \n");
        return -1;
    }
    return ret;
}

dev_open.c

cpp 复制代码
#include "timerlib.h"
int dev_open()
{
    int fd;
    fd = open("/dev/test",O_RDWR,0777);
    if(fd < 0){
        printf("file open error \n");
    }
    return fd;
}

app.c

cpp 复制代码
#include "timerlib.h"
int main(int argc,char *argv[]){
    int fd;
    fd = dev_open();
    timer_set(fd,1000);
    timer_open(fd);
    sleep(3);
    timer_set(fd,3000);
    sleep(7);
    timer_close(fd);
    close(fd);
}

驱动ioctl_timer.c

cpp 复制代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
#define TIMER_OPEN _IO('L',0)
#define TIMER_CLOSE _IO('L',1)
#define TIMER_SET _IOW('L',2,int)
 
struct device_test{
 
    dev_t dev_num;  //设备号
    int major ;  //主设备号
    int minor ;  //次设备号
    struct cdev cdev_test; // cdev
    struct class *class;   //类
    struct device *device; //设备
    int counter; 
};
static struct device_test dev1;
static void fnction_test(struct timer_list *t);//定义function_test定时功能函数
DEFINE_TIMER(timer_test,fnction_test);//定义一个定时器
void fnction_test(struct timer_list *t)
{
    printk("this is fnction_test\n");
    mod_timer(&timer_test,jiffies_64 + msecs_to_jiffies(dev1.counter));//使用mod_timer函数重新设置定时时间
}
static int cdev_test_open(struct inode *inode, struct file *file)
{
    file->private_data=&dev1;//设置私有数据
    return 0;
}
 
static int cdev_test_release(struct inode *inode, struct file *file)
{
    file->private_data=&dev1;//设置私有数据
 
    return 0;
}
 
static long cdev_test_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    struct device_test *test_dev = (struct device_test *)file->private_data;//设置私有数据
    switch(cmd){
        case TIMER_OPEN:
            add_timer(&timer_test);//添加一个定时器
            break;
        case TIMER_CLOSE:
            del_timer(&timer_test);//删除一个定时器
            break;
        case TIMER_SET:
            test_dev->counter = arg;
            timer_test.expires = jiffies_64 + msecs_to_jiffies(test_dev->counter);//设置定时时间
            break;
 
    default:
            break;
    }
    return 0;
}
/*设备操作函数*/
struct file_operations cdev_test_fops = {
    .owner = THIS_MODULE, //将owner字段指向本模块,可以避免在模块的操作正在被使用时卸载该模块
    .open = cdev_test_open,
    .release = cdev_test_release,
    .unlocked_ioctl = cdev_test_ioctl,
};
static int __init timer_dev_init(void) //驱动入口函数
{
    /*注册字符设备驱动*/
    int ret;
    /*1 创建设备号*/
    ret = alloc_chrdev_region(&dev1.dev_num, 0, 1, "alloc_name"); //动态分配设备号
    if (ret < 0)
    {
       goto err_chrdev;
    }
    printk("alloc_chrdev_region is ok\n");
 
    dev1.major = MAJOR(dev1.dev_num); //获取主设备号
    dev1.minor = MINOR(dev1.dev_num); //获取次设备号
 
    printk("major is %d \r\n", dev1.major); //打印主设备号
    printk("minor is %d \r\n", dev1.minor); //打印次设备号
     /*2 初始化cdev*/
    dev1.cdev_test.owner = THIS_MODULE;
    cdev_init(&dev1.cdev_test, &cdev_test_fops);
 
    /*3 添加一个cdev,完成字符设备注册到内核*/
   ret =  cdev_add(&dev1.cdev_test, dev1.dev_num, 1);
    if(ret<0)
    {
        goto  err_chr_add;
    }
    /*4 创建类*/
 dev1. class = class_create(THIS_MODULE, "test");
if(IS_ERR(dev1.class))
{
        ret=PTR_ERR(dev1.class);
        goto err_class_create;
    }
    /*5  创建设备*/
    dev1.device = device_create(dev1.class, NULL, dev1.dev_num, NULL, "test");
    if(IS_ERR(dev1.device))
    {
        ret=PTR_ERR(dev1.device);
        goto err_device_create;
    }
 
return 0;
 
err_device_create:
        class_destroy(dev1.class);                 //删除类
 
err_class_create:
       cdev_del(&dev1.cdev_test);                 //删除cdev
 
err_chr_add:
        unregister_chrdev_region(dev1.dev_num, 1); //注销设备号
 
err_chrdev:
        return ret;
}
 
static void __exit timer_dev_exit(void) //驱动出口函数
{
    /*注销字符设备*/
    unregister_chrdev_region(dev1.dev_num, 1); //注销设备号
    cdev_del(&dev1.cdev_test);                 //删除cdev
    device_destroy(dev1.class, dev1.dev_num);       //删除设备
    class_destroy(dev1.class);                 //删除类
}
module_init(timer_dev_init);
module_exit(timer_dev_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("quan");

Makefile

bash 复制代码
obj-m += ioctl_timer.o
KDIR:=/lib/modules/6.2.0-37-generic/build
PWD?=$(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
	echo $(PWD)
clean:
	rm -rf *.ko *.o *.mod *.mod.o *.mod.c *.symvers *.order

install:
	cp *.out *.ko ../../linux-kernel/linux-6.17.5/kmodules

编译及测试

bash 复制代码
gcc -c timer*  dev_open.c
ar rcs libtimer.a timer*.o dev_open.o
gcc app.c -L./ -ltimer
./a.out
dmesg

[114388.012997] this is fnction_test
[114389.037266] this is fnction_test
[114392.141121] this is fnction_test
[114395.213678] this is fnction_test
相关推荐
似霰1 天前
AIDL Hal 开发笔记4----驱动开发
android·驱动开发·framework·hal
yuanmenghao1 天前
车载Linux 系统问题定位方法论与实战系列 - OOM 与资源耗尽:系统是如何被“慢慢拖死”的
linux·运维·服务器·网络·驱动开发·自动驾驶
自由的好好干活2 天前
PCI9x5x驱动移植支持PCI9054在win7下使用1
驱动开发
比奇堡派星星2 天前
Linux OOM Killer
linux·开发语言·arm开发·驱动开发
Ghost Face...2 天前
网卡驱动开发与移植实战指南
驱动开发
Ghost Face...2 天前
深入解析网卡驱动开发与移植
linux·驱动开发
DeeplyMind2 天前
第7章:DRM内核调试技术:7.1 DRM DebugFS的使用
linux·驱动开发·drm·debugfs·drm debugfs
chen_mangoo3 天前
HDMI简介
android·linux·驱动开发·单片机·嵌入式硬件
食咗未3 天前
Linux microcom工具的使用
linux·运维·服务器·驱动开发·串口调试
云雾J视界4 天前
硬件试错成本太高?用Simulink构建电力电子“数字孪生体”
驱动开发·数字孪生·电力电子·simulink·sic·obc·800v