Linux 驱动开发简单实例

Xiuye_XY于 2021-08-03 19:17:07 发布343 收藏 3

分类专栏: 笔记 C/C++ Linux

版权

​编辑笔记同时被 3 个专栏收录正在上传…重新上传取消

128 篇文章0 订阅

订阅专栏

​编辑C/C++

278 篇文章2 订阅

订阅专栏

​编辑Linux

61 篇文章0 订阅

订阅专栏

驱动源码

  1. #include <linux/init.h>
  2. #include <linux/module.h>

  3. #include <linux/kernel.h>

  4. #include <linux/fs.h>

  5. #include <linux/delay.h>

  6. #define major_version 200

  7. #define driver1_name "driver1"

  8. static char read_buf[100] = "Hello driver1";

  9. static char write_buf[100];

  10. static int driver1_open(struct inode *inode,struct file *file){

  11. printk("driver1 open\r\n");

  12. return 0;

  13. }

  14. static int driver1_close(struct inode *inode,struct file *file){

  15. printk("driver1 close\r\n");

  16. return 0;

  17. }

  18. static ssize_t driver1_read(struct file *file, char __user * buf, size_t count, loff_t *ppos){

  19. printk("driver1 read\r\n");

  20. copy_to_user(buf,read_buf,count);

  21. return 0;

  22. }

  23. static ssize_t driver1_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos){

  24. int ret = 0;

  25. printk("driver1 write\r\n");

  26. ret = copy_from_user(write_buf,buf,count);

  27. if(!ret){

  28. printk("receive data: %s \r\n",write_buf);

  29. }

  30. return 0;

  31. }

  32. static struct file_operations ops={

  33. .owner = THIS_MODULE,

  34. .open = driver1_open,

  35. .release = driver1_close,

  36. .read = driver1_read,

  37. .write = driver1_write

  38. };

  39. static int __init driver1_init(void)

  40. {

  41. int ret ;

  42. printk("%s,%d\r\n", __func__, __LINE__);

  43. ret= register_chrdev(major_version,driver1_name, &ops);

  44. return ret;

  45. }

  46. static void __exit driver1_exit(void)

  47. {

  48. printk("%s,%d\r\n", __func__, __LINE__);

  49. unregister_chrdev(major_version, driver1_name);

  50. }

  51. module_init(driver1_init);

  52. module_exit(driver1_exit);

  53. MODULE_LICENSE("GPL");

Makefile文件:(像obj-m ,-C, M= 等好像是规定的,不要随便改写)

 
  1. #内核的源码路径, ?= 条件赋值, uname -r 得到内核的版本号

  2. KERNELDIR = /lib/modules/$(shell uname -r)/build

  3. # 生成模块

  4. obj-m := driver1.o

  5. # := 立即赋值, 得到当前的绝对路径

  6. PWD := $(shell pwd)

  7. # -C 切换工作路径, make -c

  8. modules:

  9. $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

  10. clean:

  11. rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules* *.mod

  12. .PHONY: modules clean

应用程序调用驱动文件:

 
  1. #include<iostream>

  2. #include<unistd.h>

  3. #include <sys/types.h>

  4. #include <sys/stat.h>

  5. #include <fcntl.h>

  6. using namespace std;

  7. int main(int argc,char*argv[]){

  8. int ret = 0;

  9. int fd = 0;

  10. char *filename;

  11. char read_buf[100],write_buf[100]="hello,driver1";

  12. if(argc < 2){

  13. cout << "cmd one param!" << endl;

  14. return -5;

  15. }

  16. filename = argv[1];

  17. fd = open(filename,O_RDWR);

  18. if(fd < 0){

  19. cout << "Cannot open file,"<<filename<< endl;

  20. return -1;

  21. }

  22. ret = read(fd,read_buf,100);

  23. if(ret < 0){

  24. cout << "read file "<<filename << " failed."<<endl;

  25. return -2;

  26. }

  27. cout<< "read buf:" << read_buf << endl;

  28. ret = write(fd,write_buf,100);

  29. if(ret <0){

  30. cout << "write file "<< filename << " failed." <<endl;

  31. return -3;

  32. }

  33. ret = close(fd);

  34. if(ret <0){

  35. cout << "close file "<< filename << " failed." <<endl;

  36. return -3;

  37. }

  38. cout << "app end" << endl;

  39. return 0;

  40. }

编译驱动

 
  1. make -C /lib/modules/5.8.0-63-generic/build M=/home/xiuye/Documents/cpp/driver1 modules

  2. make[1]: Entering directory '/usr/src/linux-headers-5.8.0-63-generic'

  3. CC [M] /home/xiuye/Documents/cpp/driver1/driver1.o

  4. MODPOST /home/xiuye/Documents/cpp/driver1/Module.symvers

  5. CC [M] /home/xiuye/Documents/cpp/driver1/driver1.mod.o

  6. LD [M] /home/xiuye/Documents/cpp/driver1/driver1.ko

  7. make[1]: Leaving directory '/usr/src/linux-headers-5.8.0-63-generic'

加载驱动

insmod driver1.ko 或者 modprobe driver1.ko

创建设备文件(如果/dev下没有驱动名的文件)

mknod /dev/driver1 c 200 0
 
  1. root@ubuntu:cpp/driver1# ls /dev/driver1

  2. /dev/driver1

  3. root@ubuntu:cpp/driver1# cat /proc/devices | grep driver1

  4. 200 driver1

应用程序调用驱动(只能在root下调用,否则失败,不知道原因):

 
  1. root@ubuntu:cpp/driver1# ./a.out /dev/driver1

  2. read buf:Hello driver1

  3. app end

查看驱动打印消息:

 
  1. root@ubuntu:cpp/driver1# dmesg

  2. [ 5062.671752] driver1_exit,76

  3. [ 5078.688136] driver1_init,63

  4. [ 5303.464000] driver1 open

  5. [ 5303.464002] driver1 read

  6. [ 5303.464030] driver1 write

  7. [ 5303.464030] receive data: hello,driver1

  8. [ 5303.464031] driver1 close

删除驱动:

 
  1. root@ubuntu:cpp/driver1# rmmod driver1

  2. root@ubuntu:cpp/driver1# dmesg

  3. [ 5438.032293] driver1_exit,76

删除设备文件,直接用 rm 命令。

echo $? 显示当前程序返回值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值