VSCode SSH 连接远程ubuntu Linux 主机
ubuntu 20.04 qemu linux6.0.1 开发环境搭建
ubuntu 20.04 qemu linux6.0.1 制作ext4根文件系统
嵌入式Linux 开发经验:platform_driver_register 的使用方法
嵌入式Linux 开发经验:注册一个 misc 设备
ubuntu 20.04
VMware Workstation Pro 16
基于qemu(模拟器),vexpress-a9 平台
Linux 6.0.10 (当前最新版本)
编写一个简单的用户态应用程序,打开与关闭 Linux 内核注册的misc 驱动设备,掌握misc 设备使用方法:打开与关闭的方法
Linux 系统分为内核态与用户态,驱动一般写在内核态,用户态想访问内核态注册的驱动设备,需要通过 文件操作 API,如 open、close、read、write、ioctl 等
Linux misc 设备,一般不提供 read 与 write,而是提供 open 、close、 ioctl 等接口,open 用于打开设备, close 用于关闭设备, 而 ioctl 虽然是一个 API,但是可以通过 命令,实现多个操作
假如 内核态的驱动设备 是个【空调】,开机后内核注册了这个设备,就像是安装在了家里,如果不【上电】,空调就无法工作,用户需要【遥控器】去操作这个【空调】,用户程序的操作就类似于【遥控器】的操作,不是直接打开【空调】盖子上电,通过【遥控器】的命令就可以实现多个操作
用户程序不需要放在 Linux 内核目录下编译,可以单独放在其他的目录,上篇注册了一个 misc 的设备,本篇写个简单的 用户态程序,打开或者关闭这个 misc 设备
编写 led_control.c,位置可以随便放,我放在 /home/zhangsz/linux/apps/led_control 目下
当前只有打开与关闭的操作,后续再实现 ioctl 控制操作
#include
#include
#include
#include #define LED_CONTROL_DEVICE_NAME "/dev/led_misc"int led_dev_fd = -1;/* 打开操作 API,这个 API其实比较的底层,也就是用户高层的应用,可以调用这个 API */
int led_dev_init(void)
{int fd;fd = open(LED_CONTROL_DEVICE_NAME, O_RDWR);if (fd < 0){printf("%s : open device error\n", __func__);return -1;}led_dev_fd = fd;printf("%s : ok\n", __func__);return 0;
}/* 关闭操作 API,这个 API其实比较的底层,也就是用户高层的应用,可以调用这个 API */
int led_dev_deinit(void)
{if (close(led_dev_fd) != 0){printf("%s : error\n", __func__);return -1;}printf("%s : ok\n", __func__);return 0;
}/* API 调用的测试,实际用户程序当然不只是这么简单 */
int main(int argc, char **argv)
{printf("%s : enter\n", __func__);led_dev_init();led_dev_deinit();printf("%s : exit\n", __func__);return 0;
}
可以直接使用命令行编译,也可以编写Makefile,因为当前的用户程序就是一个文件,所以写个简单的Makefile编译,后面就不用一直输入较长的gcc 命令来编译了
新建 Maekfile 文件,放在 /home/zhangsz/linux/apps/led_control 目下
all:arm-linux-gnueabihf-gcc led_control.c -o led_control
clean:rm -rf *.o led_control
Makefile 注意缩进使用的 TAB(制表符),而不是空格
然后在Linux shell 中 输入 make 就可以编译了
zhangsz@zhangsz:~/linux/apps/led_control$ make
arm-linux-gnueabihf-gcc led_control.c -o led_control
led_control,这个文件需要放在 Linux 根文件系统中,在 shell 手动执行这个文件才能工作,当然后期可以写个自动调用的shell 脚步放在板子上自动调用执行这里是 基于 qemu 的 ext4 的 镜像,只要把 镜像文件挂载到某个目录下,然后把 led_control 复制进去,然后 umount 后,这个文件就加入到根文件系统镜像里面了
相关操作
/* apps led_control 路径 */
zhangsz@zhangsz:~/linux/apps/led_control$ ls
led_control led_control.c Makefilezhangsz@zhangsz:~/linux/apps/led_control$ cd ../../rootfs/
zhangsz@zhangsz:~/linux/rootfs$ ls
1130 boot_qemu.sh ext4_rootfs make_rootfs.sh rootfs.ext4.img rootfs_mnt vexpress-v2p-ca9.dtb zImage/* ext4 根文件系统镜像文件,使用 mount 挂载到一个目录 */
zhangsz@zhangsz:~/linux/rootfs$ sudo mount rootfs.ext4.img rootfs_mnt/
[sudo] password for zhangsz: /* led_control 复制到 根文件系统镜像文件挂载的目录内 */
zhangsz@zhangsz:~/linux/rootfs$ sudo cp ../apps/led_control/led_control rootfs_mnt/home/root//* umount 后,文件就复制进根文件系统镜像文件中了 */
zhangsz@zhangsz:~/linux/rootfs$ sudo umount rootfs_mnt
./boot_qemu.sh rootfs.ext4.img ,这里使用的 shell 脚本,具体命令行为qemu-system-arm -M vexpress-a9 -m 512M -dtb vexpress-v2p-ca9.dtb -kernel zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.ext4.img
vexpress-v2p-ca9.dtb 与内核文件 zImage 都在同一个目录下zhangsz@zhangsz:~/linux/rootfs$ ls
1130 boot_qemu.sh ext4_rootfs make_rootfs.sh rootfs.ext4.img rootfs_mnt vexpress-v2p-ca9.dtb zImage
进入qemu Linux shell,通过 ls sys/class/misc/ -la 可以查看当前注册的 misc 设备,这里是 led_misc
进入 /home/root/ ,运行 ./led_control,可以看到 设备 打开 与关闭的信息,说明 用户应用程序成功的打开与关闭了 内核驱动 注册的 led_misc 设备
本篇记录Linux 用户态 应用程序的编写编译方法,通过标准文件接口 open close 对 内核注册的 misc 设备进行 打开与关闭。
misc 设备最有用的一般是 ioctl 命令,用户可以通过自定义实现多个 基于ioctl 的 cmd 命令,实现各种各样的操作。