• 正文
    • 在mydevice-auto.c源碼的基礎(chǔ)上進行添加,重命名為copy_to_user.c
    • 完整的copy_to_user.c示例源碼
    • 編譯
    • 編寫測試應(yīng)用源碼copy_to_user.c
    • 編譯應(yīng)用
    • 測試
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

飛凌嵌入式ElfBoard ELF 1板卡-內(nèi)核空間與用戶空間的數(shù)據(jù)拷貝之獲取內(nèi)核空間數(shù)據(jù)

03/20 17:52
535
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

例程代碼路徑:ELF 1開發(fā)板資料包3-例程源碼3-2 驅(qū)動例程源碼3_內(nèi)核空間與用戶空間的數(shù)據(jù)拷貝copy_to_user

在mydevice-auto.c源碼的基礎(chǔ)上進行添加,重命名為copy_to_user.c

(一)添加頭文件

#include <linux/uaccess.h>

(二)定義變量

#define DEVICE_NAME "copy_to_user" ?// 設(shè)備名稱

#define BUFFER_SIZE 1024

static char kernel_buffer[BUFFER_SIZE] = "Hello, User! This is kernel_buffer!";

(三)在device_read()函數(shù)添加拷貝操作,用戶空間使用read函數(shù)時,會進入此函數(shù)。

static ssize_t device_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)

{

ssize_t bytes_read = 0;

// 在這里處理設(shè)備讀取的操作

printk(KERN_INFO "This is device_read.n");

if (*offset >= BUFFER_SIZE)

return 0;

if (*offset + length > BUFFER_SIZE)

length = BUFFER_SIZE - *offset;

if (copy_to_user(buffer, kernel_buffer + *offset, length))

return -EFAULT;

*offset += length;

bytes_read = length;

return bytes_read;

}

offset參數(shù)表示當前文件位置的偏移量。它用于跟蹤讀取或?qū)懭氩僮髟谖募械奈恢谩?/p>

對于device_read函數(shù)來說,offset指向一個loff_t類型的變量,表示當前讀取操作的文件偏移量。在讀取數(shù)據(jù)之前,可以通過檢查offset來確定從文件的哪個位置開始讀取數(shù)據(jù)。讀取完成后,可以通過更新offset來指示下一次讀取操作應(yīng)該從哪個位置開始。

在使用copy_to_user()函數(shù)將數(shù)據(jù)復制到用戶空間之前,通常會更新offset的值,以確保下一次讀取操作從正確的位置開始。這樣可以實現(xiàn)逐步讀取大文件或在多次讀取中定位到不同位置的功能。

完整的copy_to_user.c示例源碼

#include <linux/module.h> ??????// 包含模塊相關(guān)函數(shù)的頭文件

#include <linux/fs.h> ??????????// 包含文件系統(tǒng)相關(guān)函數(shù)的頭文件

#include <linux/uaccess.h> ?????// 包含用戶空間數(shù)據(jù)訪問函數(shù)的頭文件

#include <linux/cdev.h> ????????//包含字符設(shè)備頭文件

#include <linux/device.h>

#include <linux/uaccess.h>

#define DEVICE_NAME "copy_to_user" ?// 設(shè)備名稱

static dev_t dev_num; ??//分配的設(shè)備號

struct ?cdev my_cdev; ?????????//字符設(shè)備指針

int major; ?//主設(shè)備號

int minor; ?//次設(shè)備號

static struct class *my_class;

static struct device *my_device;

#define BUFFER_SIZE 1024

static char kernel_buffer[BUFFER_SIZE] = "Hello, User! This is kernel_buffer!";

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

{

// 在這里處理設(shè)備打開的操作

printk(KERN_INFO "This is device_open.n");

return 0;

}

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

{

// 在這里處理設(shè)備關(guān)閉的操作

printk(KERN_INFO "This is device_release.n");

return 0;

}

static ssize_t device_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)

{

ssize_t bytes_read = 0;

// 在這里處理設(shè)備讀取的操作

printk(KERN_INFO "This is device_read.n");

if (*offset >= BUFFER_SIZE)

return 0;

if (*offset + length > BUFFER_SIZE)

length = BUFFER_SIZE - *offset;

if (copy_to_user(buffer, kernel_buffer + *offset, length))

return -EFAULT;

*offset += length;

bytes_read = length;

return bytes_read;

}

static ssize_t device_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)

{

// 在這里處理設(shè)備寫入的操作

printk(KERN_INFO "This is device_write.n");

return 0;

}

static struct file_operations fops = {

.owner = THIS_MODULE,

.open = device_open,

.release = device_release,

.read = device_read,

.write = device_write,

};

static int __init mydevice_init(void)

{

int ret;

// 在這里執(zhí)行驅(qū)動程序的初始化操作

// 注冊字符設(shè)備驅(qū)動程序

ret = alloc_chrdev_region(&dev_num,0,1,DEVICE_NAME);

if (ret < 0) {

printk(KERN_ALERT "Failed to allocate device number: %dn", ret);

return ret;

}

major=MAJOR(dev_num);

minor=MINOR(dev_num);

printk(KERN_INFO "major number: %dn",major);

printk(KERN_INFO "minor number: %dn",minor);

my_cdev.owner = THIS_MODULE;

cdev_init(&my_cdev,&fops);

cdev_add(&my_cdev,dev_num,1);

// 創(chuàng)建設(shè)備類

my_class = class_create(THIS_MODULE, "my_class");

if (IS_ERR(my_class)) {

pr_err("Failed to create classn");

return PTR_ERR(my_class);

}

// 創(chuàng)建設(shè)備節(jié)點并關(guān)聯(lián)到設(shè)備類

my_device = device_create(my_class, NULL, MKDEV(major, minor), NULL, DEVICE_NAME);

if (IS_ERR(my_device)) {

pr_err("Failed to create devicen");

class_destroy(my_class);

return PTR_ERR(my_device);

}

printk(KERN_INFO "Device registered successfully.n");

return 0;

}

static void __exit mydevice_exit(void)

{

// 在這里執(zhí)行驅(qū)動程序的清理操作

// 銷毀設(shè)備節(jié)點

device_destroy(my_class, MKDEV(major, minor));

// 銷毀設(shè)備類

class_destroy(my_class);

// 刪除字符設(shè)備

cdev_del(&my_cdev);

// 注銷字符設(shè)備驅(qū)動程序

unregister_chrdev(0, DEVICE_NAME);

printk(KERN_INFO "Device unregistered.n");

}

module_init(mydevice_init);

module_exit(mydevice_exit);

MODULE_LICENSE("GPL"); ?????// 指定模塊的許可證信息

MODULE_AUTHOR("Your Name"); // 指定模塊的作者信息

MODULE_DESCRIPTION("A simple character device driver"); // 指定模塊的描述信息

編譯

復制7.3.4驅(qū)動中的Makefile文件,將其中的mydevice-auto.o修改為copy_to_user.o,效果如下:

. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

elf@ubuntu:~/work/test/03_內(nèi)核空間與用戶空間的數(shù)據(jù)拷貝/copy_to_user$ make

將驅(qū)動模塊編譯成.ko并拷貝到開發(fā)板中。

編寫測試應(yīng)用源碼copy_to_user.c

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/ioctl.h>

#include <errno.h>

#include <fcntl.h>

#include <string.h>

#define DEV_NAME "/dev/copy_to_user"

#define BUFFER_SIZE 1024

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

{

int reg;

int fd = 0;

char read_buffer[BUFFER_SIZE];

fd = open (DEV_NAME, O_RDWR);

if (fd < 0) {

perror("Open "DEV_NAME" Failed!n");

exit(1);

}

if (read(fd, read_buffer, BUFFER_SIZE) < 0) {

printf("Failed to read from device file: %sn", DEV_NAME);

close(fd);

exit(1);

}

printf("Read from device file: %sn", read_buffer);

close(fd);

return 0;

}

編譯應(yīng)用

. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

elf@ubuntu:~/work/test/03_內(nèi)核空間與用戶空間的數(shù)據(jù)拷貝/copy_to_user_app$ $CC?copy_to_user.c -o copy_to_user

將編譯好的應(yīng)用程序拷貝到開發(fā)板中。

測試

root@ELF1:~# insmod copy_to_user.ko

major number: 249

minor number: 0

Device registered successfully.

root@ELF1:~# ./copy_to_user

This is device_open.

This is device_read.

Read from device file: Hello, UseThis is device_release.

r! This is kernel_buffer!

root@ELF1:~# rmmod copy_to_user.ko

Device unregistered.

可以看到運行測試程序后,把內(nèi)核空間中kernel_buffer[]中的數(shù)據(jù)打印了出來。

飛凌嵌入式

飛凌嵌入式

保定飛凌嵌入式技術(shù)有限公司,創(chuàng)建于2006年,是一家專注嵌入式核心控制系統(tǒng)研發(fā)、設(shè)計和生產(chǎn)的高新技術(shù)企業(yè),是國內(nèi)較早專業(yè)從事嵌入式技術(shù)的企業(yè)之一。 經(jīng)過十幾年的發(fā)展與積累,公司擁有業(yè)內(nèi)優(yōu)秀的軟硬件研發(fā)團隊,在北京及保定建立兩大研發(fā)基地,在蘇州、深圳設(shè)有華東、華南技術(shù)服務(wù)中心,并在北美、歐洲以及亞太等其他國家和地區(qū)擁有國際業(yè)務(wù)網(wǎng)絡(luò)。公司研發(fā)的智能設(shè)備核心平臺廣泛應(yīng)用于物聯(lián)網(wǎng)、工控、軌道交通、醫(yī)療、電力、商業(yè)電子、智能家居、安防、機器人、環(huán)境監(jiān)測等諸多領(lǐng)域。

保定飛凌嵌入式技術(shù)有限公司,創(chuàng)建于2006年,是一家專注嵌入式核心控制系統(tǒng)研發(fā)、設(shè)計和生產(chǎn)的高新技術(shù)企業(yè),是國內(nèi)較早專業(yè)從事嵌入式技術(shù)的企業(yè)之一。 經(jīng)過十幾年的發(fā)展與積累,公司擁有業(yè)內(nèi)優(yōu)秀的軟硬件研發(fā)團隊,在北京及保定建立兩大研發(fā)基地,在蘇州、深圳設(shè)有華東、華南技術(shù)服務(wù)中心,并在北美、歐洲以及亞太等其他國家和地區(qū)擁有國際業(yè)務(wù)網(wǎng)絡(luò)。公司研發(fā)的智能設(shè)備核心平臺廣泛應(yīng)用于物聯(lián)網(wǎng)、工控、軌道交通、醫(yī)療、電力、商業(yè)電子、智能家居、安防、機器人、環(huán)境監(jiān)測等諸多領(lǐng)域。收起

查看更多

相關(guān)推薦