Ubuntu駆動開発環境の構築


1、linux-5.0.1 ubuntu 1910を使用
2、インストール依存
build-essential
kernel-package
gcc
make
libncurses5-dev
libssl-dev
libelf-dev

sudo apt-get install...
3、ソースファイルの取得とインストール
3.1、カーネルソースの取得
#         
uname -r
5.0.0-32-generic
#       
sudo apt-get install linux-source-5.0.0
#       /usr/src 
cd /usr/src
linux-source-5.0.0.bz2
#        
sudo tar -jxvf linux-source-5.0.0.bz2 -C ~/linux-kernel
#        
cd ~/linux-kernel/linux-source-5.0.0

3.2、インストール
#   
sudo make oldconfig
#    
sudo make
#      
sudo make modules
sudo make modules_install
#  lib/modules        
cd /lib/modules
yang@yang-Lenovo:/lib/modules$ ll
    20
drwxr-xr-x   5 root root 4096 11  16 14:30 ./
drwxr-xr-x 142 root root 4096 11  12 20:37 ../
drwxr-xr-x   5 root root 4096 4   17  2019 5.0.0-13-generic/
drwxr-xr-x   5 root root 4096 11  12 11:22 5.0.0-32-generic/
drwxr-xr-x   3 root root 4096 11  16 14:35 5.0.21/


(注意:私の実行コンパイルsudo make oldconfigでエラーが発生します.解決方法:bison sudo apt-get install basionをインストールします(少なくとも私の場合は解決できます))
4、テスト
(ホームディレクトリの下に直接ディレクトリを作成します)
yang@yang-Lenovo:~/my_cdev$ ls
chr_dev_test.c  led_dev.c  Makefile  my_chr_dev.c

(led_dev.cを無視)1)文字デバイスドライバファイル:my_chr_dev.c
#include 
#include 
#include 
#include 
#include 
#include 

#define BASEMINOR 0
#define COUNT     2
#define NAME      "led_dev"

dev_t dev_num;
struct cdev *cdevp = NULL;

static char kernel_val = 6;

//      int open(const char *pathname, int flags);
int open_cdev(struct inode *ino, struct file *filp)
{
	printk("open_cdev secuss
"
); return 0; } // ssize_t read(int fd, void *buf, size_t count); ssize_t read_cdev(struct file *filp, char __user *buf, size_t count, loff_t *loff) { int ret; ret = copy_to_user(buf, &kernel_val, count); if(ret > 0) { printk("copy_to_user error
"
); return -1; } return 0; } // write ssize_t write_cdev(struct file *filp, const char __user *buf, size_t count, loff_t *loff) { char value; int ret; ret = copy_from_user(&value, buf, count); if(ret > 0) { printk("copy_from_user error
"
); return -2; } printk("From user data: %d
"
, value); return 0; } struct file_operations fops = { .owner = THIS_MODULE, .open = open_cdev, .write = write_cdev, .read = read_cdev }; static int my_cdev_init(void) { int ret; //1、 ret = alloc_chrdev_region(&dev_num, BASEMINOR, COUNT, NAME); if(ret < 0){ printk("alloc_chrdev_region failed
"
); return -1; } //2、 cdev cdevp = cdev_alloc(); if(NULL == cdevp) { printk("cdev_alloc failed
"
); unregister_chrdev_region(dev_num, COUNT); return -2; } //3、 cdev_init(cdevp, &fops); //4、 ret = cdev_add(cdevp, dev_num, COUNT); if(ret < 0){ printk("cdev_add failed
"
); unregister_chrdev_region(dev_num, COUNT); return -3; } printk("major = %d
"
, MAJOR(dev_num)); printk("my_cdev_init sucess
"
); return 0; } static void my_cdev_del(void) { //5、 cdev_del(cdevp); //6、 unregister_chrdev_region(dev_num, COUNT); printk("my_cdev_del sucess
"
); } module_init(my_cdev_init); module_exit(my_cdev_del); MODULE_LICENSE("GPL");

2)Makefile
ifneq ($(KERNELRELEASE),)
obj-m := my_chr_dev.o

else
PWD  := $(shell pwd)
KVER := $(shell uname -r) 
KDIR := /lib/modules/`uname -r`/build

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
	rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.*
endif


3)テストファイル:chr_dev_test.c
#include "stdio.h"
#include "fcntl.h"
#include "unistd.h"

int main(void)
{
	int ret;
	int fd;
	char rd_buf;

	fd = open("/dev/led0", O_RDONLY);
	if(fd < 0)
	{
		printf("open failed
"
); return -1; } read(fd, &rd_buf, 1); printf("rd_buf = %d
"
, rd_buf); close(fd); return 0; }

検証手順を実行するには、1)自分が作成したディレクトリの下に入り、makeと直接入力します.
yang@yang-Lenovo:~$ cd ./my_cdev/
yang@yang-Lenovo:~/my_cdev$ ls
chr_dev_test.c  led_dev.c  Makefile  my_chr_dev.c
yang@yang-Lenovo:~/my_cdev$ make
make -C /lib/modules/`uname -r`/build M=/home/yang/my_cdev modules
make[1]:/usr/src/linux-headers-5.0.0-32-generic”
  CC [M]  /home/yang/my_cdev/my_chr_dev.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/yang/my_cdev/my_chr_dev.mod.o
  LD [M]  /home/yang/my_cdev/my_chr_dev.ko
make[1]:/usr/src/linux-headers-5.0.0-32-generic”
yang@yang-Lenovo:~/my_cdev$ ls
chr_dev_test.c  modules.order   my_chr_dev.ko     my_chr_dev.o
led_dev.c       Module.symvers  my_chr_dev.mod.c
Makefile        my_chr_dev.c    my_chr_dev.mod.o


2)登録文字デバイス:
sudo insmod my_chr_dev.ko

その後、デバイスに複数の文字デバイスled_が表示されます.dev:
cat /proc/devices

116 alsa
128 ptm
136 pts
180 usb
189 usb_device
204 ttyMAX
226 drm
*238 led_dev*
239 vfio
240 aux
241 mei
242 hidraw


3)文字デバイスに対応するノードを作成する:
yang@yang-Lenovo:~/my_cdev$ sudo mknod /dev/led0 c 238 0  //  :238     , 0     
yang@yang-Lenovo:~/my_cdev$ ll /dev/led0
crw-r--r-- 1 root root 238, 0 11  16 15:24 /dev/led0


4)テストプログラムの実行:(3)yangユーザーはled 0に対して‘r’権限しかないことがわかるので、テストファイルにはwriteをテストしていません.もちろん権限を修正することでwriteをテストすることができます)
yang@yang-Lenovo:~/my_cdev$ gcc chr_dev_test.c
yang@yang-Lenovo:~/my_cdev$ ./a.out
rd_buf = 6

5)デバイスノードを削除する:
sudo rm /dev/led0

6)文字デバイスのアンインストール:
sudo rmmod my_chr_dev.ko

(参照リンク:https://blog.csdn.net/Xin_101/article/details/84791761)