国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

linux內核開發(fā)第6講:應用層的write怎么樣調用到驅動里的write

這篇具有很好參考價值的文章主要介紹了linux內核開發(fā)第6講:應用層的write怎么樣調用到驅動里的write。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1.應用層code

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>

#define DATA_NUM (64)

int main() {
    int fd, i;
    int r_len, w_len;
    fd_set fdset;

    char buf[DATA_NUM] = "hello world";
    memset(buf, 0, DATA_NUM);
    fd = open("/dev/hello", O_RDWR);
    printf("%d\n", fd);
    if (fd == -1) {
        printf("open file error\n");
        return -1;
    }
    else {
        printf("open success\n");
    }

    w_len = write(fd, buf, DATA_NUM);
    r_len = read(fd, buf, DATA_NUM);
    printf("w_len %d r_len %d\n", w_len, r_len);
    return 0;
}

2.設備文件

代碼中的open的“/dev/hello”是個設備文件
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ ls -lh /dev/hello
ls: 無法訪問'/dev/hello': 沒有那個文件或目錄
現(xiàn)在還沒有創(chuàng)建這個設備文件
大部分驅動可以自動創(chuàng)建設備文件
也可以手動的創(chuàng)建設備文件

可以使用mknod命令創(chuàng)建設備文件
mknod [OPTION]... NAME TYPE [MAJOR MINOR]
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ sudo mknod /dev/hello c 232 0
[sudo] zhaoxr 的密碼:
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ ls -lh /dev/hello
crw-r--r-- 1 root root 232, 0 424 22:39 /dev/hello
查看驅動 lsmod 
lsmod查看的是insmod的.ko文件
這個.ko文件的名字來自makefile文件的驅動名稱

cat /proc/devices
查看列出字符和塊設備的主設備號,以及分配到這些設備號的設備名稱。
這個設備名稱來自register_chrdev_region的第三個參數(shù)

3.應用層程序調用驅動過程

3.1 編寫驅動helloDev.c

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/slab.h>

#define BUFFER_MAX (10)
#define OK (0)
#define ERROR (-1)

struct cdev *gDev = NULL;
struct file_operations *gFile = NULL;
dev_t devNum;
unsigned int subDevNum = 1;
int reg_major= 232;
int reg_minor = 0;
char *buffer = NULL;
int flag = 0;

int hello_open(struct inode *p, struct file *f) {
    printk(KERN_EMERG "hello_open\r\n");
    return 0;
}

ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l) {
    printk(KERN_EMERG "hello_write\r\n");
    return 0;
}

ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l) {
    printk(KERN_EMERG "hello_read\r\n");
    return 0;
}

int hello_init(void) {
    devNum = MKDEV(reg_major, reg_minor);
    if (OK == register_chrdev_region(devNum, subDevNum, "helloworld")) {
        printk(KERN_EMERG "register_chrdev_region ok\n");
    }
    else {
        printk(KERN_EMERG "register_chrdev_region error\n");
        return ERROR;
    }
    printk(KERN_EMERG "hello driver init\n");
    gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
    gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
    gFile->open = hello_open;
    gFile->read = hello_read;
    gFile->write = hello_write;
    gFile->owner = THIS_MODULE;
    cdev_init(gDev, gFile);
    cdev_add(gDev, devNum, 3);
    return 0;
}

void __exit hello_exit(void) {
    cdev_del(gDev);
    unregister_chrdev_region(devNum, subDevNum);
    return;
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

3.2 編寫驅動的makefile

ifneq ($(KERNELRELEASE),)
obj-m := helloDev.o
else

PWD := $(shell pwd)
$(info "$(PWD)")
KDIR := /lib/modules/$(shell uname -r)/build
$(info "$(KDIR)")
all:
	make -C $(KDIR) M=$(PWD)
clean:
	rm -rf *.o *.ko *.mod.c *.symvers *.c~ *~ *.mod *.order
endif

3.3 編寫應用層程序main.c

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


#define DATA_NUM (64)

int main() {
    int fd, i;
    int r_len, w_len;
    fd_set fdset;

    char buf[DATA_NUM] = "hello world";
    memset(buf, 0, DATA_NUM);
    fd = open("/dev/hello", O_RDWR);
    printf("%d\n", fd);
    if (fd == -1) {
        printf("open file error\n");
        return -1;
    }
    else {
        printf("open success\n");
    }

    w_len = write(fd, buf, DATA_NUM);
    r_len = read(fd, buf, DATA_NUM);
    printf("w_len %d r_len %d\n", w_len, r_len);
    return 0;
}

3.4 編寫應用層makefile

out : main.o
	gcc -o out main.o
main.o : main.c
	gcc -c main.c

clean :
	rm -rf *.o out

3.5編譯驅動和加載驅動

zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ make
"/home/zhaoxr/xiangrui.zhao/linux_kernel"
"/lib/modules/5.15.0-69-generic/build"
make -C /lib/modules/5.15.0-69-generic/build M=/home/zhaoxr/xiangrui.zhao/linux_kernel
make[1]: 進入目錄“/usr/src/linux-headers-5.15.0-69-generic”
  CC [M]  /home/zhaoxr/xiangrui.zhao/linux_kernel/helloDev.o
  MODPOST /home/zhaoxr/xiangrui.zhao/linux_kernel/Module.symvers
  CC [M]  /home/zhaoxr/xiangrui.zhao/linux_kernel/helloDev.mod.o
  LD [M]  /home/zhaoxr/xiangrui.zhao/linux_kernel/helloDev.ko
  BTF [M] /home/zhaoxr/xiangrui.zhao/linux_kernel/helloDev.ko
Skipping BTF generation for /home/zhaoxr/xiangrui.zhao/linux_kernel/helloDev.ko due to unavailability of vmlinux
make[1]: 離開目錄“/usr/src/linux-headers-5.15.0-69-generic”
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ ls
helloDev.c  helloDev.ko  helloDev.mod  helloDev.mod.c  helloDev.mod.o  helloDev.o  Makefile  modules.order  Module.symvers  user
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ sudo insmod helloDev.ko

Message from syslogd@zhaoxr-ThinkPad-E450 at Apr 25 22:47:40 ...
 kernel:[169201.833551] register_chrdev_region ok

Message from syslogd@zhaoxr-ThinkPad-E450 at Apr 25 22:47:40 ...
 kernel:[169201.833556] hello driver init
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ lsmod
Module                  Size  Used by
helloDev               16384  0
rfcomm                 81920  4
ccm                    20480  6

3.6 創(chuàng)建驅動對應的設備文件

利用主次設備號,創(chuàng)建驅動對應的設備文件,并設置權限,以方便應用層訪問
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ sudo mknod /dev/hello c 232 0
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ ls -lh /dev/hello
crw-r--r-- 1 root root 232, 0 425 22:52 /dev/hello
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ sudo chmod 777 /dev/hello
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel$ ls -lh /dev/hello
crwxrwxrwx 1 root root 232, 0 425 22:52 /dev/hello

3.7 編譯應用層程序并執(zhí)行

zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel/user$ make
gcc -c main.c
main.c: In function ‘main’:
main.c:28:13: warning: implicit declaration of function ‘write’; did you mean ‘fwrite’? [-Wimplicit-function-declaration]
   28 |     w_len = write(fd, buf, DATA_NUM);
      |             ^~~~~
      |             fwrite
main.c:29:13: warning: implicit declaration of function ‘read’; did you mean ‘fread’? [-Wimplicit-function-declaration]
   29 |     r_len = read(fd, buf, DATA_NUM);
      |             ^~~~
      |             fread
gcc -o out main.o
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel/user$ ls
main.c  main.o  Makefile  out
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel/user$ ./out
3
open success
w_len 0 r_len 0
zhaoxr@zhaoxr-ThinkPad-E450:~/xiangrui.zhao/linux_kernel/user$
Message from syslogd@zhaoxr-ThinkPad-E450 at Apr 25 22:54:55 ...
 kernel:[169637.294848] hello_open

Message from syslogd@zhaoxr-ThinkPad-E450 at Apr 25 22:54:55 ...
 kernel:[169637.295049] hello_write

Message from syslogd@zhaoxr-ThinkPad-E450 at Apr 25 22:54:55 ...
 kernel:[169637.295056] hello_read

4.write的調用過程

應用層調用write,首先會調用C庫函數(shù),然后通過系統(tǒng)調用進入到內核里面。
內核中關于write的系統(tǒng)調用
在linux源代碼的fs目錄下有read_write.c文件

首先是SYSCALL_DEFINE
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
		size_t, count)
{
	struct fd f = fdget_pos(fd);
	ssize_t ret = -EBADF;

	if (f.file) {
		loff_t pos = file_pos_read(f.file);
		ret = vfs_write(f.file, buf, count, &pos);
		if (ret >= 0)
			file_pos_write(f.file, pos);
		fdput_pos(f);
	}

	return ret;
}
然后是vfs_write
ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
	ssize_t ret;

	if (!(file->f_mode & FMODE_WRITE))
		return -EBADF;
	if (!(file->f_mode & FMODE_CAN_WRITE))
		return -EINVAL;
	if (unlikely(!access_ok(VERIFY_READ, buf, count)))
		return -EFAULT;

	ret = rw_verify_area(WRITE, file, pos, count);
	if (!ret) {
		if (count > MAX_RW_COUNT)
			count =  MAX_RW_COUNT;
		file_start_write(file);
		ret = __vfs_write(file, buf, count, pos);
		if (ret > 0) {
			fsnotify_modify(file);
			add_wchar(current, ret);
		}
		inc_syscw(current);
		file_end_write(file);
	}

	return ret;
}
然后是__vfs_write
ssize_t __vfs_write(struct file *file, const char __user *p, size_t count,
		    loff_t *pos)
{
	if (file->f_op->write)
		return file->f_op->write(file, p, count, pos);
	else if (file->f_op->write_iter)
		return new_sync_write(file, p, count, pos);
	else
		return -EINVAL;
}
由于fd對應的file->f_op->write存在,因此會調用到我們自己驅動編寫的hello_write

文章來源地址http://www.zghlxwxcb.cn/news/detail-426422.html

到了這里,關于linux內核開發(fā)第6講:應用層的write怎么樣調用到驅動里的write的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【Linux】應用層之HTTP協(xié)議

    【Linux】應用層之HTTP協(xié)議

    在應用層,需要我們傳遞應用層所需特殊的數(shù)據(jù)格式,這種數(shù)據(jù)可能是連續(xù)數(shù)據(jù),例如int類型的整形變量,也可能是string類型的字符串,也可能是多個變量構成的結構體,那么就意味著我們發(fā)送的數(shù)據(jù)可能是連續(xù)的,也可能是不連續(xù)的,這時為了統(tǒng)一數(shù)據(jù)的解析方法,我們對

    2024年02月12日
    瀏覽(31)
  • Linux網絡:應用層之HTTP協(xié)議

    Linux網絡:應用層之HTTP協(xié)議

    我們程序員寫的一個個解決實際問題,滿足日常需求的網絡程序,都是在應用層。 協(xié)議是一種約定。網絡協(xié)議是計算機網絡中通信雙方都必須遵守的一組約定。 在網絡通信中,都是以 “字符串” 的方式來發(fā)送和接收數(shù)據(jù)的。 如果要發(fā)送和接收一些結構化的數(shù)據(jù),就需要序

    2023年04月26日
    瀏覽(19)
  • 【Linux】應用層協(xié)議:HTTP和HTTPS

    【Linux】應用層協(xié)議:HTTP和HTTPS

    每個人都可以很喜歡每個人,但喜歡治不了病,喜歡買不了東西,喜歡不能當飯吃,喜歡很廉價… 1.1 URL的組成 1. 在之前的文章中我們實現(xiàn)了一個網絡版本的計算器,在那個計算器中揉合了協(xié)議定制以及序列化反序列化的內容,我們當時也自己定制了一套協(xié)議標準,比如請求

    2024年02月10日
    瀏覽(17)
  • 【Linux】【驅動】應用層和驅動層傳輸數(shù)據(jù)

    【Linux】【驅動】應用層和驅動層傳輸數(shù)據(jù)

    Linux一切皆文件! 文件對應的操作有打開,關閉,讀寫設備節(jié)點對應的操作有打開,關閉,讀寫 當我們在應用層 read 設備節(jié)點的時候,就會觸發(fā)我們驅動里面read 這個函數(shù) 當我們在應用層 write 設備節(jié)點的時候,就會觸發(fā)我們驅動里面 write 這個函數(shù) 如下兩個代碼實現(xiàn)了數(shù)據(jù)的

    2024年02月12日
    瀏覽(20)
  • Linux在應用層上使用I2C

    通常情況下i2c讀寫一般是在kernel中使用,但是在應用層上一樣可以使用。在應用上可以通過讀寫/dev/i2c-x這個節(jié)點從而控制i2c接口進行讀寫數(shù)據(jù)。 通常一個SOC有多個I2C控制器,假設有這個SOC有3個控制器,我們會在/dev目錄下看到i2c-0、i2c-1、i2c-2,計數(shù)從0開始。 1.首先使用的時

    2024年02月02日
    瀏覽(28)
  • 【Linux網絡】網絡應用層的 http 和 https協(xié)議

    【Linux網絡】網絡應用層的 http 和 https協(xié)議

    在之前學習序列化和反序列化的時候,認識到主機之間傳輸結構數(shù)據(jù)的時候,最好是通過某種約定將結構數(shù)據(jù)序列化成一串字符串,接收方再通過反序列化將字符串轉換成結構數(shù)據(jù)。以上說的這種約定,其實可以看成是用戶層通信的一種協(xié)議,是由程序猿自己定的。 ? 實際

    2024年02月02日
    瀏覽(25)
  • 【Linux】應用層協(xié)議序列化和反序列化

    【Linux】應用層協(xié)議序列化和反序列化

    歡迎來到Cefler的博客?? ??博客主頁:折紙花滿衣 ??個人專欄:題目解析 ??推薦文章:C++【智能指針】 前言 在正式代碼開始前,會有一些前提知識引入 在網絡應用層中,序列化(Serialization)和反序列化(Deserialization)是將數(shù)據(jù)轉換為可在網絡上傳輸?shù)母袷?,并從網絡接

    2024年04月23日
    瀏覽(46)
  • Linux C/C++實現(xiàn)SSL的應用層VPN (MiniVPN)

    Linux C/C++實現(xiàn)SSL的應用層VPN (MiniVPN)

    SSL協(xié)議和VPN(虛擬私人網絡)原理是網絡安全領域中的兩個重要概念。 SSL協(xié)議,全稱安全套接層(Secure Sockets Layer),是一種廣泛應用于互聯(lián)網的安全協(xié)議,主要在兩個通信端點之間建立安全連接,以保護數(shù)據(jù)的傳輸安全。具體來說,SSL通過使用公鑰加密算法實現(xiàn)數(shù)據(jù)的加密

    2024年02月08日
    瀏覽(17)
  • 【音視頻|ALSA】基于alsa-lib開發(fā)ALSA應用層程序--附帶源碼

    【音視頻|ALSA】基于alsa-lib開發(fā)ALSA應用層程序--附帶源碼

    ??博客主頁??:??https://blog.csdn.net/wkd_007?? ??博客內容??:??嵌入式開發(fā)、Linux、C語言、C++、數(shù)據(jù)結構、音視頻?? ??本文內容??:??基于alsa-lib開發(fā)ALSA應用層程序?? ??金句分享??:??蓋士人讀書,第一要有志,第二要有識,第三要有恒。有志則斷不甘為下流,有

    2024年02月08日
    瀏覽(32)
  • 基于MATLAB開發(fā)AUTOSAR軟件應用層Code mapping專題-part 3 Paramter標簽頁介紹

    基于MATLAB開發(fā)AUTOSAR軟件應用層Code mapping專題-part 3 Paramter標簽頁介紹

    這頁是參數(shù)設置的界面,那首先要知道什么是參數(shù),參數(shù)就是算法中的系數(shù)這些可以更改的變量,接下來就是要學習如何創(chuàng)建參數(shù),如下圖: 打開模型資源管理器 選擇model Workspace標簽,點擊上邊工具欄里的創(chuàng)建參數(shù)的按鈕(紅色箭頭指向的按鈕),添加一個新的參數(shù)K,值設置

    2024年02月11日
    瀏覽(87)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包