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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux字符设备驱动的 ioctl 幻数

發(fā)布時間:2024/9/21 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux字符设备驱动的 ioctl 幻数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
在Linux字符設(shè)備驅(qū)動入門(一)中,我們實現(xiàn)了字符設(shè)備的簡單讀寫字符功能,接下來我們要在這個基礎(chǔ)上加入ioctl功能。首先,我們先來看看3.0內(nèi)核下../include/linux/fs.h中file_operations結(jié)構(gòu)體的定義:


struct file_operations {
?? ?struct module *owner;
?? ?loff_t (*llseek) (struct file *, loff_t, int);
?? ?ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
?? ?ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
?? ?ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
?? ?ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
?? ?int (*readdir) (struct file *, void *, filldir_t);
?? ?unsigned int (*poll) (struct file *, struct poll_table_struct *);
?? ?long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
?? ?long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

?? ?int (*mmap) (struct file *, struct vm_area_struct *);
?? ?int (*open) (struct inode *, struct file *);
?? ?int (*flush) (struct file *, fl_owner_t id);
?? ?int (*release) (struct inode *, struct file *);
?? ?int (*fsync) (struct file *, int datasync);
?? ?int (*aio_fsync) (struct kiocb *, int datasync);
?? ?int (*fasync) (int, struct file *, int);
?? ?int (*lock) (struct file *, int, struct file_lock *);
?? ?ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
?? ?unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
?? ?int (*check_flags)(int);
?? ?int (*flock) (struct file *, int, struct file_lock *);
?? ?ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
?? ?ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
?? ?int (*setlease)(struct file *, long, struct file_lock **);
?? ?long (*fallocate)(struct file *file, int mode, loff_t offset,
?? ??? ??? ?? loff_t len);
};

????? 紅色字體已經(jīng)標(biāo)出在kernel 3.0中已經(jīng)完全刪除了struct file_operations 中的ioctl 函數(shù)指針,剩下unlocked_ioctlcompat_ioctl,取而代之的是unlocked_ioctl,主要改進(jìn)就是不再需要上大內(nèi)核鎖 (調(diào)用之前不再先調(diào)用lock_kernel()然后再unlock_kernel())。

?????? 所以,在hellow.c中,我們在file_operations中加入成員函數(shù)hello_ioctl(紅色字體部分):

/* file operations for hello device */
static struct file_operations hello_ops = {
?? ?.owner = THIS_MODULE,
?? ?.unlocked_ioctl = hello_ioctl,
?? ?.open = hello_open,
?? ?.read = hello_read,
?? ?.write = hello_write,
?? ?.release = hello_release,
};

hello_ioctl()的定義如下:

static int hello_ioctl( struct file *file,
?? ??? ??? ?unsigned int cmd, unsigned long arg)
{?? ?int temp = 0;
?? ?switch(cmd)
?? ?{
?? ?? case HELLO_CMD1:
?? ??? ??????? {
?? ??? ??? ?temp = 1;
?? ??? ??? ?if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;
?? ??? ??? ?break;
?? ??? ??????? }
?? ?? case HELLO_CMD2:
?? ??? ??? ?{
?? ??? ??? ?temp = 2;
?? ??? ??? ?if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;
?? ??? ??? ?break;
?? ??? ??? ?}
?? ?}
?? ?printk( KERN_NOTICE"ioctl CMD%d done!\n",temp);?? ?

return 0;

}


這里強調(diào)一下cmd的定義:

#define HELLO_MAGIC 'k'
#define HELLO_CMD1?? ?_IO(HELLO_MAGIC,0x1a)
#define HELLO_CMD2?? ?_IO(HELLO_MAGIC,0x1b)

其中'k'為幻數(shù),要按照Linux內(nèi)核的約定方法為驅(qū)動程序選擇ioctl編號,應(yīng)該首先看看include/asm/ioctl.h和Documentation/ioctl-number.txt這兩個文件,下面是ioctl.h的部分內(nèi)容,也是比較重要的:

_IO(type, nr)?用于構(gòu)造無參數(shù)的命令編號;
_IOR(type, nr, datatype)?用于構(gòu)造從驅(qū)動程序中讀取數(shù)據(jù)的命令編號;
_IOW(type, nr, datatype)用于寫入數(shù)據(jù)的命令;
_IOWR(type, nr, datatype)用于雙向傳輸。
注意千萬不能重復(fù)定義。


注意對幻數(shù)的編號千萬不能重復(fù)定義,如ioctl-number.txt已經(jīng)說明‘k'的編號已經(jīng)被占用的范圍為:

'k'?? ?00-0F?? ?linux/spi/spidev.h?? ?conflict!
'k'?? ?00-05?? ?video/kyro.h?? ??? ?conflict!

???? 所以我們在這里分別編號為0x1a和0x1b,到這里,我們已經(jīng)完成了對ioctl功能的編寫,接下來就是在測試程序中利用系統(tǒng)調(diào)用來測試它。

=============================================================

ioctl測試程序

=============================================================
#include <stdio.h> ?
#include <fcntl.h> ?
#include <stdlib.h> ?
#include <string.h> ?
#include <sys/types.h> ?
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define HELLO_MAGIC 'k'? //當(dāng)然我們也可以定義一個相應(yīng)的頭文件,把ioctl的cmd放進(jìn)里面,然后再include進(jìn) 來
#define HELLO_CMD1?? ?_IO(HELLO_MAGIC,0x1a)
#define HELLO_CMD2?? ?_IO(HELLO_MAGIC,0x1b)

? ?? ?int main(void)
{
?? ?int ioctl_rdata;
?? ?int fd, ret;

??? fd = open ( "/dev/hellow" , O_RDWR);
?? ?if ( fd == -1 )
?? ?{
?? ?? perror("open");
?? ?? exit(0);
?? ??? ?}

??? ret = ioctl( fd, HELLO_CMD2,&ioctl_rdata);
?? ?if ( ret == -1)
?? ?{
?? ? perror("ioctl");
?? ? exit(0);
?? ?}
?? ?printf("ioctl_rdata= %d \n",ioctl_rdata);

?? ?close(fd);
?? ?return 0;
}
=============================================================

運行結(jié)果

=============================================================

root@Ubuntu:~/share/hellow# insmod hellow.ko
root@Ubuntu:~/share/hellow# mknod /dev/hellow c 251 0
root@Ubuntu:~/share/hellow# ./a.out
ioctl_rdata= 2?
root@Ubuntu:~/share/hellow# dmesg | tail

[ 2431.126532] hello init. major:251, minor:0
[ 2453.326022] Hello device open!

[ 2453.326047] ioctl CMD2 done!
[ 2453.326487] Hello device close!

總結(jié)

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

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