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

歡迎訪問 生活随笔!

生活随笔

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

linux

linux字符驱动头文件路径,Linux 字符设备驱动例子

發布時間:2025/3/20 linux 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux字符驱动头文件路径,Linux 字符设备驱动例子 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

編寫好驅動,通過掛載的方法將驅動程序掛載到內核里面,大致步驟如下:

一: ?1>建立以.c為后綴的c語言程序文件 (里面包含了設備名及設備號等)

2>建立Makefile文件(作用是通過make來產生設備文件*.ko文件,里面可以建立自己的平臺所需的設備文件如:arm等).make 產生相應的設備文件

二: 要在/dev下建立相應的設備結點(設備名),用insomd *.ko命令將相應的驅動設備文件掛載到內核中.

三:編寫測試文件(.c文件)用來測試內核是否已近成功掛載到內核.(編寫好相應的測試文件后,用gcc –o Filename Filename.c(測試文件名) 來產生相應的可執行文件).

四:如果設備驅動掛載成功,當執行測試文件(./Filename)時會產生相應的結果.

五:可能用到的相關命令:

1. ? ? ? lsmod:列出內核已經載入模塊的專題.

輸出:

Module(模塊名) ? ? ? ? ? ?size(大小) ? ? ? ? ? ?used by (被..使用)

2. ? ? ? demop:分析可加載模塊的依賴性,生成modules.dep文件和映射文件

3. ? ? ? uname –r ? 顯示內核版本(在編寫Makefile時使用到)

4. ? ? ? modprobe : linux 內核添加和刪除模塊(相關參數請查看man幫助文檔)

5. ? ? ? modinfo:顯示內核模塊的信息.

6. ? ? ? insmod: 向linux內核中加載一個模塊,用法:insmod ?[filename] [module options…]

7. ? ? ? rmmod: 刪除內核中的模塊, 用法: rmmod [-f,w,s,v] ? ? ? [modulename]

8. ? ? ? dmesg: 顯示內核緩沖區,內核的各種信息,內核啟動時的信息會寫入到/var/log/下.

六.例子

第一步:增加頭文件和宏定義

#include

#include

#include

#include

#include

#include

第二步:添加與字符設備定義及注冊有關的數據成員

//定義設備名稱

#define DEVICE_NAME "test" //設備名

#define BUF_SIZE 1024

static char tmpbuf[BUF_SIZE];

//定義主次設備號

static unsigned int TestMajor=0; //主

static unsigned int TestMinor=0; //次

static struct cdev *test_cdev;

static dev_t dev;

第三步:增加open/release函數

static int test_chardev_open(struct inode *inode,struct file *file)

{

printk("open major=%d, minor=%d\n", imajor(inode),

iminor(inode));

return 0;

}

static int test_chardev_release(struct inode *inode,struct file *file)

{

printk("close major=%d,minor=%d\n",imajor(inode),

iminor(inode));

return 0;

}

第四步:增加read函數

static ssize_t test_chardev_read(struct file *file,char __user *buf,

size_t const count,loff_t *offset)

{

if(count < BUF_SIZE)

{

if(copy_to_user(buf,tmpbuf,count))

{

printk("copy to user fail \n");

return -EFAULT;

}

}else{

printk("read size must be less than %d\n", BUF_SIZE);

return -EINVAL;

}

*offset += count;

return count;

}

第五步:增加write函數

static ssize_t test_chardev_write(struct file *file, const char __user *buf,size_t const count,loff_t *offset)

{

if(count < BUF_SIZE)

{

if(copy_from_user(tmpbuf,buf,count))

{

printk("copy from user fail \n");

return -EFAULT;

}

}else{

printk("size must be less than %d\n", BUF_SIZE);

return -EINVAL;

}

*offset += count;

return count;

}

第六步:添加增加file_operations 成員

static struct file_operations chardev_fops={

.owner = THIS_MODULE,

.read = test_chardev_read,

.write = test_chardev_write,

.open = test_chardev_open,

.release = test_chardev_release,

};

第七步:在模塊的入口添加設備的設備號獲取及設備注冊

static int __init chrdev_init(void)

{

int result;

if(TestMajor)

{

dev=MKDEV(TestMajor,TestMinor);//創建設備編號

result=register_chrdev_region(dev,1,DEVICE_NAME);

} else {

result=alloc_chrdev_region(&dev,TestMinor,1,DEVICE_NAME);

TestMajor=MAJOR(dev);

}

if(result<0)

{

printk(KERN_WARNING"LED: cannot get major %d \n",TestMajor);

return result;

}

test_cdev=cdev_alloc();

cdev_init(test_cdev,&chardev_fops);

//test_cdev->ops=&chardev_fops;

test_cdev->owner=THIS_MODULE;

result=cdev_add(test_cdev,dev,1);

if(result)

printk("<1>Error %d while register led device!\n",result);

return 0;

}

第八步:在模塊的出口函數增加設備設備號釋放及設備注銷函數

unregister_chrdev_region(MKDEV(TestMajor,TestMinor),1);

cdev_del(test_cdev);

第九步:編譯并加載該模塊

第十步:根據設備號的設置,在文件系統中建立對應的設備節點

$mknod /dev/test ?c ?XXX(主設備號) ?XX(次設備號)

完整例子

驅動文件

#include

#include

#include

#include

#include

#include

#define DEVICENAME "ccccc"

unsigned int major=221;

unsigned int minor=0;

struct cdev *abc;

dev_t dev;

static char bufrh[1024]="read success!";

static int aaaaa_open(struct inode *inodep, struct file *filep)

{

printk("read success!\n");

return 0;

}

int aaaaa_release(struct inode *inodep, struct file *filep)

{

return 0;

}

static ssize_t aaaaa_read (struct file *filep, char __user *buf, size_t count, loff_t *offset)

{

if(copy_to_user(buf, bufrh, 1))

{

printk("copy_to_user fail!\n");

}

return 0;

}

ssize_t aaaaa_write (struct file *filep, const char __user *buf, size_t count, loff_t *offse)

{

printk("write!\n");

return 0;

}

static const struct file_operations fops = {

.owner = THIS_MODULE,

.open = aaaaa_open,

.release = aaaaa_release,

.read = aaaaa_read,

.write = aaaaa_write,

};

static int __init aaaaa_init(void)

{

int a;

dev=MKDEV(major, minor);

a=register_chrdev_region(dev, 1, DEVICENAME);

abc=cdev_alloc();

abc->owner=THIS_MODULE;

cdev_init(abc, &fops);

cdev_add(abc, dev, 1);

return 0;

}

static void __exit aaaaa_cleanup(void)

{

cdev_del(abc);

unregister_chrdev_region(dev, 1);

}

module_init(aaaaa_init);

module_exit(aaaaa_cleanup);

MODULE_LICENSE("GPL ");

Makefile文件

obj-m += firstqd.o(相應設備文件名)

KERDIR = /usr/src/linux-headers-2.6.32-24-generic #x86平臺

PWD=$(shell pwd)

modules:

$(MAKE) -C $(KERDIR) M=$(PWD) modules

pc:

gcc -o fristqd firstqd.c

arm:

arm-linux-gcc -o fristqd firstqd.c

clean:

rm -rf *.o *~core *.depend *.cmd *.ko *.mod.c *.tmp_versions

用戶空間測試代碼

#include

#include

#include

char buf[1024];

char bufw[1024]="write success";

int main()

{

int fd,m,n;

fd=open("/dev/aaa",O_RDWR);

if (fd)

{

m=read(fd,buf,100);

printf("read kernel:%s\n",buf);

n=write(fd,bufw,10);

}

//printf("ni hao");

return 0;

}

總結

以上是生活随笔為你收集整理的linux字符驱动头文件路径,Linux 字符设备驱动例子的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。