linux 驱动开发之linux vscode环境搭建以及第一个驱动 helloWorld

本文介绍如何使用VSCode在Linux环境下搭建嵌入式驱动开发环境,包括下载与安装VSCode、配置ARM交叉编译工具链、创建与编译HelloWorld驱动模块,并将其加载到目标板的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 下载linux版的vscode ,并且安装

  2. 我用的板子是nxp的imx6ull,下载nxp的的arm交叉编译工具链和他们的内核(也可以下载官方版本的内核和编译工具链),解压并设置路径,我的路径如下:
    内核路径/home/mayunzhi/linux/Linux-4.9.88
    工具链路径/home/mayunzhi/linux/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/

  3. 创建一个helloworld的文件夹mkdir helloworld ,创建一个c文件:touch helloworld.c

  4. 用vscode打开文件夹helloworld 编辑helloworld.c

 #include <linux/module.h>
 
 static int __init hello_init(void){
    printk(KERN_INFO"hello world init !\n");
     return 0;
  }
  static void __exit hello_exit(void){
     printk(KERN_INFO"hello world exit !\n");
 }
 
 module_init(hello_init);
 module_exit(hello_exit);
 MODULE_LICENSE("GPL");
  1. 创建Makefile   touch Makefile
  2. 编辑Makefile
KERNELDIR :=/home/mayunzhi/linux/Linux-4.9.88
 
CURRENT_PATH :=$(shell pwd)
 
build:kernel_modules
 
kernel_modules:
 
  $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
 
clean:
 
  $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
  1. 在vscode下打开终端,默认当前目录为helloworld文件夹下,执行make命令

  2. 产生这些文件:
    helloworld.mod.c helloworld.mod.o modules.order helloworld.ko helloworld.o

  3. 后缀名为.ko的文件就是我们开发板需要的模块驱动文件,将helloworld.ko拷贝到开发板文件系统里的/lib/module/4.1.15/中,这里是通过nfs环境,(后面会有详细的教程).

  4. 在开发板中cd到/lib/module/4.1.15/,执行insmod helloworld.ko命令将helloworld驱动加载到内核,在开发板终端会看到"hello world init !"的信息
    5.要卸载驱动只需要在当前目录下执行rmmod helloworld.ko,就可以卸载helloworld驱动,会看到终端有"hello world exit !"的信息

以上就是一个最简单的helloworld的linux 驱动设计方式,只是输出了信息,没有涉及soc上的硬件操作,比如gpio,中断,i2c,spi,lcd等等,当然我们的驱动开发远没有这么简单,后面我会详细介绍,

<think>好的,我现在需要为完全的小白设计一个入门Linux驱动的教程,要求详细到每一步,包括在哪里新建什么文件等。首先,我得回想自己当初学习Linux驱动开发的经历,那时候最困惑的是什么,可能有哪些步骤容易出错。 用户是完全的小白,所以必须从最基础的环境搭建开始。可能需要先安装Linux系统,比如Ubuntu,因为对新手比较友好。然后需要安装必要的开发工具,比如gcc、make、内核头文件等。这部分要详细说明具体的安装命令,确保用户能正确执行。 接下来,可能需要介绍Linux内核模块的基本概念,因为编写驱动通常是以模块的形式加载的。这里要解释模块是什么,如何编写一个最简单的模块,比如“Hello World”例子。需要创建源代码文件,比如hello.c,并编写模块的初始化函数和退出函数。 然后,编写Makefile是关键步骤,因为用户可能不知道如何编译模块。需要详细说明Makefile的内容,特别是如何指向当前的内核构建目录。可能还需要提醒用户根据实际内核版本调整路径。 编译成功后,要指导用户使用insmod和rmmod加载和卸载模块,并用dmesg查看内核日志,确认模块是否正常工作。这部分需要具体的命令示例,确保用户能够复制粘贴执行。 在用户成功运行第一个模块后,可能需要进一步引导他们实现一个简单的字符设备驱动,比如创建一个可以读写的设备。这里需要涉及注册字符设备、创建设备文件(使用mknod),以及实现file_operations结构体中的read和write函数。 同时,要提醒用户注意权限问题,比如使用sudo执行某些命令,以及设备文件的主次设备号是否正确。可能还需要提到动态分配设备号的方法,避免与现有设备冲突。 安全方面,可能需要提醒用户在虚拟机中进行实验,避免对主机系统造成影响。此外,错误处理也很重要,比如模块加载失败时如何查看错误信息。 最后,应该提供进一步学习的资源,如推荐书籍、在线文档或社区,帮助用户继续深入学习。整个教程需要循序渐进,每个步骤都验证用户的成果,确保他们能够跟上并理解每个部分的作用。</think>以下是一个从零开始的Linux驱动开发入门教程,适合完全小白的实践指南(建议在Ubuntu 20.04/22.04环境下操作): --- ### 第1步:环境准备 ```bash # 安装编译工具链和内核头文件 sudo apt update sudo apt install build-essential linux-headers-$(uname -r) ``` --- ### 第2步:创建第一个内核模块 1. 新建工作目录并创建源文件 ```bash mkdir ~/my_first_driver && cd ~/my_first_driver touch hello.c Makefile ``` 2. 编辑hello.c(使用vim/nano/vscode等工具) ```c #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("YourName"); static int __init hello_init(void) { printk(KERN_INFO "Hello World!\n"); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO "Goodbye World!\n"); } module_init(hello_init); module_exit(hello_exit); ``` 3. 编辑Makefile(注意空格使用Tab缩进) ```makefile obj-m += hello.o KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build all: make -C $(KERNEL_DIR) M=$(PWD) modules clean: make -C $(KERNEL_DIR) M=$(PWD) clean ``` --- ### 第3步:编译和测试模块 ```bash # 编译模块(生成hello.ko文件) make # 加载模块(需要root权限) sudo insmod hello.ko # 查看内核日志(显示Hello World!) dmesg | tail -n 1 # 卸载模块 sudo rmmod hello # 再次查看日志(显示Goodbye World!) dmesg | tail -n 1 ``` --- ### 第4步:创建字符设备驱动 1. 新建chardev.c ```c #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #define DEVICE_NAME "my_chardev" static dev_t dev_num; static struct cdev my_cdev; static int device_open(struct inode *inode, struct file *file) { printk(KERN_INFO "Device opened\n"); return 0; } static ssize_t device_read(struct file *filp, char __user *buf, size_t len, loff_t *off) { const char *msg = "Hello from kernel!\n"; size_t msg_len = strlen(msg); if (*off >= msg_len) return 0; if (len > msg_len - *off) len = msg_len - *off; if (copy_to_user(buf, msg + *off, len)) return -EFAULT; *off += len; return len; } static struct file_operations fops = { .owner = THIS_MODULE, .open = device_open, .read = device_read, }; static int __init chardev_init(void) { // 动态申请设备号 if (alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME) < 0) return -1; cdev_init(&my_cdev, &fops); if (cdev_add(&my_cdev, dev_num, 1) < 0) { unregister_chrdev_region(dev_num, 1); return -1; } printk(KERN_INFO "Char device registered, major=%d minor=%d\n", MAJOR(dev_num), MINOR(dev_num)); return 0; } static void __exit chardev_exit(void) { cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1); printk(KERN_INFO "Char device unregistered\n"); } module_init(chardev_init); module_exit(chardev_exit); ``` 2. 更新Makefile ```makefile obj-m += hello.o chardev.o ``` --- ### 第5步:测试字符设备 ```bash # 编译驱动 make # 加载字符设备驱动 sudo insmod chardev.ko # 查看分配的设备号(记下major编号) dmesg | tail -n 1 # 创建设备文件(假设major=242) sudo mknod /dev/my_chardev c 242 0 sudo chmod 666 /dev/my_chardev # 测试设备读取 cat /dev/my_chardev # 应该显示"Hello from kernel!" ``` --- ### 后续学习建议 1. 推荐书籍: - 《Linux设备驱动程序》(O'Reilly经典) - 《Linux Kernel Development》 2. 重要目录: - 内核源码:/usr/src/linux-headers-$(uname -r) - 设备信息:/proc/devices - 模块信息:/sys/module/ 3. 调试技巧: - 使用printk输出调试信息 - 通过dmesg -w实时查看内核日志 - 使用strace跟踪系统调用 **注意:驱动开发需要root权限操作内核空间,建议在虚拟机中进行实验!**
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值