當前位置:編程學習大全網 - 源碼下載 - ubuntu中如何找到最新增加的設備節點

ubuntu中如何找到最新增加的設備節點

將自己開發的內核代碼加入到Linux內核中,需要3個步驟:

1、確定把自己開發代碼放入到內核合適的位置

將demo_chardev.c文件拷貝到.../drivers/char/目錄下。

demo_chardev.c

[cpp] view plain copy

#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

/*結構體file_operations定義的頭文件*/

#include <linux/fs.h>

/*聲明copy_to/from_user函數的頭文件*/

#include <linux/uaccess.h>

/*聲明class_create 和device_create相關信息*/

#include <linux/device.h>

#define DEMO_DEBUG

#ifdef DEMO_DEBUG

#define dem_dbg(fmt, arg...) printk(KERN_WARNING fmt, ##arg)

#else

#define dem_dbg(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)

#endif

#define DEVICE_COUNT 2

/*記錄當前驅動所占用的主設備號*/

static int major = 0;

static int demo_open (struct inode *pnode, struct file *filp)

{

dem_dbg("[kern func]: %s major: %d minor: %d\n",

__FUNCTION__, imajor(pnode), iminor(pnode));

return 0;

}

static ssize_t demo_read (struct file *filp, char __user *buf, size_t count, loff_t *offp)

{

unsigned char ary[100] = "you are reading successfully!";

unsigned long len = min(count, sizeof(ary)); //min是個宏,用來獲取兩個數中較小的值

int retval;

dem_dbg("[kern func]: %s major: %d minor: %d\n",

__FUNCTION__, imajor(filp->f_dentry->d_inode),

iminor(filp->f_dentry->d_inode));

//file結構體的f_flags成員可用來判斷是否阻塞讀取,然後進行相應處理

if(copy_to_user(buf, ary, len) != 0){

retval = -EFAULT;

goto cp_err;

}

return len; //成功返回實際傳輸的字節數

cp_err:

return retval;

}

static ssize_t demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)

{

unsigned char ary[100] = "";

unsigned long len = min(count, sizeof(ary)); //min是個宏,用來獲取兩個數中較小的值

int retval;

dem_dbg("[kern func]: %s major: %d minor: %d\n",

__FUNCTION__, imajor(filp->f_dentry->d_inode),

iminor(filp->f_dentry->d_inode));

if(copy_from_user(ary, buf, len) != 0){

retval = -EFAULT;

goto cp_err;

}

printk("[msg]: writing context: %s\n",ary);

return len; //成功返回實際傳輸的字節數

cp_err:

return retval;

}

static int demo_release (struct inode *pnode, struct file *filp)

{

dem_dbg("[kern func]: %s major: %d minor: %d\n",

__FUNCTION__, imajor(pnode), iminor(pnode));

return 0;

}

/*@定義file_operations結構體變量*/

static struct file_operations fops = {

.owner = THIS_MODULE,

.read = demo_read,

.write = demo_write,

.open = demo_open,

.release = demo_release,

};

static struct class *demo_class;

static int __init drvdemo_init(void)

{

struct device *demo_device;

int i;

int retval;

dem_dbg("[msg]:this is a driver demo, in module initial function\n");

/*註冊字符驅動函數,成功 返回動態分配好的主設備號,失敗

*返回錯誤碼(負值)*/

major = register_chrdev(0, "demo_chrdev", &fops);

if(major < 0){

retval = major;

goto chrdev_err;

}

/*創建設備類*/

demo_class = class_create(THIS_MODULE,"demo_class");

if(IS_ERR(demo_class)){

retval = PTR_ERR(demo_class);

goto class_err;

}

/*創建設備文件,通知用戶在“/dev/”目錄下創件名字為demoX的設備文件*/

for(i=0; i<DEVICE_COUNT; i++){ //最多可創建255個設備節點(register_chrdev函數會申請0-254範圍的從設備號)

demo_device = device_create(demo_class,NULL, MKDEV(major, i), NULL,"demo%d",i);

if(IS_ERR(demo_device)){

retval = PTR_ERR(demo_device);

goto device_err;

}

}

return 0;

device_err:

while(i--) //設備節點創建的回滾操作 device_destroy(demo_class,MKDEV(major, i));

class_destroy(demo_class); //刪除設備類

class_err:

unregister_chrdev(major, "demo_chrdev");

chrdev_err:

return retval;

}

static void __exit drvdemo_exit(void)

{

int i;

dem_dbg("[msg]:in module exit function\n");

/*註銷字符驅動函數,無返回值,major為已分配的主設備號*/

unregister_chrdev(major, "demo_chrdev");

/*刪除設備節點和設備類*/

for(i=0; i<DEVICE_COUNT; i++)

device_destroy(demo_class,MKDEV(major, i));

class_destroy(demo_class);

}

module_init(drvdemo_init);

module_exit(drvdemo_exit);

MODULE_LICENSE("Dual BSD/GPL"); //BSD/GPL雙重許可證

MODULE_AUTHOR("hanbo"); //模塊作者(可選)

MODULE_DESCRIPTION("used for studing linux drivers"); //模塊兒簡介(可選)

2、把自己開發的功能增加到Linux內核的配置選項中,使用戶能夠選擇此功能

vi drivers/char/Konfig 在文件結尾,endmenu的前面加入壹個config選項

[cpp] view plain copy

config DEMO_CHARDEV

bool "demo_chardev driver for hanbo chardev boards"

default y

help

this is CHARDEV driver for hanbo chardev boards.

3、構建或修改Makefile,根據用戶的選擇,將相應的代碼編譯到最終生成的Linux內核中去

make menuconfig(添加配置選項)(如果提示找不到“ncurses”庫則執行命令: sudo apt-get install libncurses5-dev )

Device driver -->

character devices ->

[*] demo_chardev driver for hanbo chardev boards

4、vi drivers/char/Makefile 添加內容如下:

..........

obj-$(CONFIG_DEMO_CHARDEV) +=demo_chardev.o (添加)

obj-$(CONFIG_JS_RTC) +=js-rtc.o(自帶)

js-rtc-y = rtc.o (自帶)

5、make (更新內核鏡像到開發板)

6、交叉編譯測試程序,放到開發板運行

arm-linux-gcc-gcc test.c -o demo

test.c

[cpp] view plain copy

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <fcntl.h>

#include <string.h>

int main(int argc, char *argv[])

{

int fd1 = 0, fd2 = 0;

unsigned char buf1[100] = "I am a test program!";

unsigned char buf2[100] = {0};

int retval;

//以讀寫、不阻塞方式打開設備文件

fd1 = open("/dev/demo0", O_RDWR | O_NONBLOCK);

if(fd1 < 0){

perror("open /dev/demo1");

goto out;

}

//以只讀、阻塞方式打開設備文件

fd2 = open("/dev/demo1", O_RDONLY);

if(fd2 < 0){

perror("open /dev/demo2");

goto out;

}

//成功返回實際寫入字節數,失敗返回負值

retval = write(fd1, buf1, strlen(buf1)+1);

if(retval < 0){

perror("writing fd1 failed!");

goto out;

}

printf("<user space>: write bytes: %d write content: %s\n", retval, buf1);

//成功返回實際讀取字節數,失敗返回負值

retval = read(fd2, buf2, sizeof(buf2));

if(retval < 0){

perror("reading fd2 failed!");

goto out;

}

printf("<user space>: read bytes: %d read content: %s\n", retval, buf2);

return 0;

out:

if(fd1 > 0)

close(fd1);

if(fd2 > 0)

close(fd2);

return -1;

}

二、手動加載驅動 .ko文件

1、上面的demo_chardev.c文件放到內核下編譯生成 .ko文件

Makefile

[cpp] view plain copy

#如果已定義KERNELRELEASE,說明是由內核構造系統調用的

#可以利用內建語句

ifneq ($(KERNELRELEASE),)

obj-m +=demo_chrdev.o

#此時由內核構造系統調用

else

#定義並記錄內核源碼路徑

KERNELDIR = /home/hanbo/linux-2.6.35.7(自己源碼路徑,2.6.35.7指當前內核版本)

#記錄當前工程目錄

PWD := $(shell pwd)

default:

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

@rm -rf *.o .t* .m* .*.cmd *.mod.c *.order *.symvers

endif

clean:

rm -rf *.ko *.o .t* .m* .*.cmd *.mod.c *.order *.symvers

2、 然後用命令加載 .ko 驅動

lsmod 列舉當前系統中的所有模塊

lsmod 列舉當前系統中的所有模塊

rmmod xxx 卸載指定模塊(不需要.ko後綴)

3、如果自己編譯的代碼中沒有用

/*創建設備類*/

demo_class = class_create(THIS_MODULE,"demo_class");

/*創建設備文件,通知用戶在“/dev/”目錄下創件名字為demoX的設備文件*/

demo_device = device_create(demo_class,NULL, MKDEV(major, i), NULL,"demo%d",i);

則需要手動添加設備節點

mknod /dev/demo1 c 主設備號 0

mknod /dev/demo2 c 主設備號 1

註意:若卸載時出現提示 rmmod:chdir(2.6.35.7):No such file or directory

則在開發板根文件系統下創建目錄:/lib/modules/2.6.35.7(跟當前內核版本同名)

  • 上一篇:最新源代碼的預售
  • 下一篇:《LOL》關鍵詞查詢工具系統
  • copyright 2024編程學習大全網