Linux 驱动例程

这是一个较为完整的Linux驱动的例程
编译环境:

curtis@curtis-virtual-machine:~/Desktop/tdriver$ uname -r
5.4.0-42-generic
curtis@curtis-virtual-machine:~/Desktop/tdriver$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

chr_drv.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>

//静态的指定
int ret;
static unsigned int dev_major = 101; 
static struct class *devcls;
static struct device *dev;

static int kernel_val = 555;

//read(fd,buff,size)
ssize_t chr_drv_read (struct file *filp, char __user *buf, size_t count, loff_t *fpos)
{
    
    
     int ret;
     printk("-----------%s--------------\n",__FUNCTION__);

     ret = copy_to_user(buf, &kernel_val,count);
     if(ret > 0)
     {
    
    
      printk("copy_to_user error!\n");
      return -EFAULT;
     }
     return 0;
}

ssize_t chr_drv_write (struct file *filp, const char __user *buf, size_t count, loff_t *fpos)
{
    
    
     int ret;
     int value;

     printk("-----------%s--------------\n",__FUNCTION__);

     ret = copy_from_user(&value, buf ,count);
     if(ret > 0)
     {
    
    
      printk("copy_from_user error!\n");
      return -EFAULT;
     }
     printk("___KERNEL___  : %d \n",value);
     return 0;
}

int chr_drv_open (struct inode *inode, struct file *filp)
{
    
    
     printk("-----------%s--------------\n",__FUNCTION__);
     return 0;
}


int chr_drv_close (struct inode *inode, struct file *filp)
{
    
    

     printk("-----------%s--------------\n",__FUNCTION__);
     return 0;
}

const struct file_operations my_fops = 
{
    
    
  .open = chr_drv_open,
  .read = chr_drv_read,
  .write = chr_drv_write,
  .release = chr_drv_close,
};


static int __init chr_drv_init(void)
{
    
    
  //一般申请设备资源
  //申请设备号
  register_chrdev(dev_major, "chr_dev_test", &my_fops);//cat/proc/devices
  if(ret == 0)
  {
    
    
    printk("register ok\n");
  }
  else{
    
    
    printk("register failed\n");
    return -EINVAL;
  }

  devcls = class_create(THIS_MODULE, "chr_cls");
  dev = device_create(devcls, NULL,
           MKDEV(dev_major,0), NULL, "chr2");//dev/chr2

  return 0;
}

static void __exit chr_drv_exit(void)
{
    
    
   //一般是释放资源

   device_destroy(devcls, MKDEV(dev_major,0));
   class_destroy(devcls);
   unregister_chrdev(dev_major, "chr_dev_test");  
}

module_init(chr_drv_init);
module_exit(chr_drv_exit); 
MODULE_LICENSE("GPL");

Makefile:

CONFIG_MODULE_SIG=n

ifeq ($(KERNELRELEASE),)

ROOTS_DIR = /root/
#内核源码路径,不同环境可能会不一样,内核源码一定要先编译
KERNEL_DIR = /lib/modules/$(shell uname -r)/build
CUR_DIR = $(shell pwd)

all: 
	make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
clean :
	make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
install:
	insmod chr_drv.ko
uninstall:
	rmmod chr_drv
		
else
#用于指定到底编译的是哪个代码--hello.c
obj-m += chr_drv.o
#obj-m += math.o
endif

应用程序chr_test.c

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h>

int main(int arvc, char *argv[])
{
    
    
  //调用驱动

  int fd;
  int value = 0;
  //返回文件描述符,设备从/dev/里读,和驱动所对应的设备节点一致
  fd = open("/dev/chr2",O_RDWR);
  if(fd < 0)
  {
    
    
    perror("open");
    exit(1);
  }

  read(fd,&value,4);

  printf("___USER____:%d\n",value );

  //重新给value赋值

  value = 666;

  write(fd,&value,4);

  close(fd);

  return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_42931917/article/details/108447127