日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux_2.6字符设备驱动实例

發(fā)布時間:2023/12/9 linux 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux_2.6字符设备驱动实例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第一步:my74hc595.c

#include <linux/module.h> //模塊所需的大量符號和函數(shù)定義
#include <linux/init.h> //指定初始化和清除函數(shù)
#include <linux/fs.h> //文件系統(tǒng)相關的函數(shù)和頭文件
#include <linux/cdev.h> //cdev結(jié)構(gòu)的頭文件
#include <asm/uaccess.h> //在內(nèi)核和用戶空間中移動數(shù)據(jù)的函數(shù)
#include <linux/slab.h>
#include <linux/device.h>

MODULE_LICENSE("GPL"); //指定代碼使用的許可證

//文件操作函數(shù)的聲明
int my74hc595_open(struct inode *, struct file *);
int my74hc595_release(struct inode *, struct file *);
ssize_t my74hc595_read(struct file *, char *, size_t, loff_t *);
ssize_t my74hc595_write(struct file *, const char *, size_t, loff_t *);

int dev_major = 1253; //指定主設備號
int dev_minor = 0; //指定次設備號

static struct class *firstdrv_class;
static struct device *firstdrv_class_dev;

struct cdev *my74hc595_cdev; //內(nèi)核中表示字符設備的結(jié)構(gòu)
int *gp_testdata;//測試用數(shù)據(jù)

struct file_operations my74hc595_fops= //將文件操作與分配的設備號相連
{
  owner: THIS_MODULE, //指向擁有該模塊結(jié)構(gòu)的指針
  open: my74hc595_open,
  release: my74hc595_release,
  read: my74hc595_read,
  write: my74hc595_write,
};

static void __exit my74hc595_exit(void) //退出模塊時的操作
{
  dev_t devno=MKDEV(dev_major, dev_minor); //dev_t是用來表示設備編號的結(jié)構(gòu)

  cdev_del(my74hc595_cdev); //從系統(tǒng)中移除一個字符設備
  kfree(my74hc595_cdev); //釋放自定義的設備結(jié)構(gòu)
  kfree(gp_testdata);
  unregister_chrdev_region(devno, 1); //注銷已注冊的驅(qū)動程序

  device_unregister(firstdrv_class_dev); //刪除/dev下對應的字符設備節(jié)點
  class_destroy(firstdrv_class);

  printk("my74hc595 unregister success\n");
}

static int __init my74hc595_init(void) //初始化模塊的操作
{
  int ret, err;
  dev_t devno;
#if 1
  //動態(tài)分配設備號,次設備號已經(jīng)指定
  ret=alloc_chrdev_region(&devno, dev_minor, 1, "my74hc595");
  //保存動態(tài)分配的主設備號
  dev_major=MAJOR(devno);

#else
  //根據(jù)期望值分配設備號
  devno=MKDEV(dev_major, dev_minor);
  ret=register_chrdev_region(devno, 1, "my74hc595");
#endif

  if(ret<0)
  {
    printk("my74hc595 register failure\n");
    //my74hc595_exit(); //如果注冊設備號失敗就退出系統(tǒng)
    return ret;
  }
  else
  {
    printk("my74hc595 register success\n");
  }

  gp_testdata = kmalloc(sizeof(int), GFP_KERNEL);
#if 0//兩種初始化字符設備信息的方法
  my74hc595_cdev = cdev_alloc();//調(diào)試時,此中方法在rmmod后會出現(xiàn)異常,原因未知
  my74hc595_cdev->ops = &my74hc595_fops;
#else
  my74hc595_cdev = kmalloc(sizeof(struct cdev), GFP_KERNEL);
  cdev_init(my74hc595_cdev, &my74hc595_fops);
#endif

  my74hc595_cdev->owner = THIS_MODULE; //初始化cdev中的所有者字段

  err=cdev_add(my74hc595_cdev, devno, 1); //向內(nèi)核添加這個cdev結(jié)構(gòu)的信息
  if(err<0)
    printk("add device failure\n"); //如果添加失敗打印錯誤消息

  firstdrv_class = class_create(THIS_MODULE, "my74hc595");
  firstdrv_class_dev = device_create(firstdrv_class, NULL, MKDEV(dev_major, 0), NULL,"my74hc595-%d", 0);//在/dev下創(chuàng)建節(jié)點

  printk("register my74hc595 dev OK\n");

  return 0;
}
//打開設備文件系統(tǒng)調(diào)用對應的操作
int my74hc595_open(struct inode *inode, struct file *filp)
{
  //將file結(jié)構(gòu)中的private_data字段指向已分配的設備結(jié)構(gòu)
  filp->private_data = gp_testdata;
  printk("open my74hc595 dev OK\n");
  return 0;
}
//關閉設備文件系統(tǒng)調(diào)用對應的操作
int my74hc595_release(struct inode *inode, struct file *filp)
{
  printk("close my74hc595 dev OK\n");
  return 0;
}
//讀設備文件系統(tǒng)調(diào)用對應的操作
ssize_t my74hc595_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
  //獲取指向已分配數(shù)據(jù)的指針
  unsigned int *p_testdata = filp->private_data;
  //將設備變量值復制到用戶空間
  if(copy_to_user(buf, p_testdata, sizeof(int)))
  {
    return -EFAULT;
  }
  printk("read my74hc595 dev OK\n");
  return sizeof(int); //返回讀取數(shù)據(jù)的大小
}
//寫設備文件系統(tǒng)調(diào)用對應的操作
ssize_t my74hc595_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
  //獲取指向已分配數(shù)據(jù)的指針
  unsigned int *p_testdata = filp->private_data;
  //從用戶空間復制數(shù)據(jù)到內(nèi)核中的設備變量
  if(copy_from_user(p_testdata, buf, sizeof(int)))
  {
    return -EFAULT;
  }
  printk("write my74hc595 dev OK\n");
  return sizeof(int); //返回寫數(shù)據(jù)的大小
}

module_init(my74hc595_init); //模塊被裝載時調(diào)用my74hc595_init
module_exit(my74hc595_exit); //模塊被卸載時調(diào)用my74hc595_exit

?

第二步:Makefile

按如下內(nèi)容編寫一個Makefile文件,然后輸入make就可以開始自動編譯了。編譯之后得到了一個名為my74hc595.ko的模塊文件,這就是我們需要的設備驅(qū)動文件。

?

#Makefile
CROSS_COMPILE=arm-linux-
ARCH:=arm
CC:=$(CROSS_COMPILE)gcc
LD:=$(CROSS_COMPILE)ld
obj-m = my74hc595.o
module-objs = my74hc595.o

KDIR = /home/zhang/at91/linux-at91
PWD = $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -rf *.o *.ko *~

?

接下來運行如下代碼,將驅(qū)動加入內(nèi)核。

insmod my74hc595.ko

將自動在/dev目錄下創(chuàng)建設備節(jié)點

rmmod?my74hc595.ko

將自動刪除節(jié)點

?

第三步:CharDevTest.c

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

main()
{
  int fd, num;
  // fd=open("/dev/my74hc595", O_RDWR, S_IRUSR|S_IWUSR); //可讀寫方式打開設備文件
  fd=open("/dev/my74hc595-0", O_RDWR); //可讀寫方式打開設備文件
  if(fd!=-1)
  {
    read(fd, &num, sizeof(int)); //讀取設備變量
    printf("The my74hc595 is %d\n", num);

    printf("Please input the num written to my74hc595\n");
    scanf("%d", &num);
    write(fd, &num, sizeof(int)); //寫設備變量

    read(fd, &num, sizeof(int)); //再次讀取剛才寫的值
    printf("The my74hc595 is %d\n", num);

    close(fd); //關閉設備文件
  }
  else
  {
    printf("Device open failure\n");
    perror("open my74hc595");
  }
}

轉(zhuǎn)載于:https://www.cnblogs.com/Charles-Zhang-Blog/p/3454382.html

總結(jié)

以上是生活随笔為你收集整理的Linux_2.6字符设备驱动实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。