关于 ioctl 函数
ioctl函数是用于控制的设备的接口
1.底层: long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long args);
file_operations结构中的一个函数指针成员,具体的函数接口是自己实现的。
参数:args是4字节的类型,可以传递整型数据,也可以传递指针,指针的话就可以传递一个结构,在cmd中的size位域传递这个结构的字节大小
2.应用层:int ioctl(int fd, int request, ...);
功能:ioctl() 函数操纵特殊文件的底层设备参数。
参数:fd: 文件描述符
request :请求cmd 关于cmd命令制作参考下面介绍
...:可变参数 char *p;
返回值: 成功: 0 失败: -1
3.关于cmd:
其中对于request(cmd)即命令的操作,要保证值的唯一性。
cmd就是一个数,是应用层传递给驱动的值,在驱动中对应的这个值是否有操作,自己实现。
内核使用几个宏来制作cmd:
_IO : 不传递参数 #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
_IOW : 只写方式 #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
_IOR :只读方式 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
_IOWR :读写方式 #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
cmd 中各 bit 对应的功能

|-----------|-------------|----------|-----------|
|31 30 |29 16 | 15 8 |7 0 |
|-----------|-------------|----------|-----------|
| dir | size | type | nr |
|-----------|-------------|----------|-----------|
cmd 命令码中相应位对应的功能:
dir :方向: 读 _IOR 写 _IOW 可读可写_IOWR _IO(type,nr) //没有第三个参数 ...
size :13位 ---->传递的数据类型(char short int ...struct )的大小 2^14 = 16384
type :8位 类型----> 给定一个ASCII码, a-z =====>幻数magic 借助这个幻数让cmd更加唯一 ==类似共享内存中构建键值的== ftok
nr :8位 命令码的序号: 2^8 = 256;对设备的控制状态,对命令码中一般不使用2号,内核貌似已使用
通过这几个宏制作一个cmd命令,然后通过ioctl传递到底层的demo_ioctl中判断cmd对应的nr位域执行对应的操作。
简单例子:
-------demo.c驱动程序
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/uaccess.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/kfifo.h>
#include "demo.h" /* 变量定义区域 */
const char * name = "demochdrev"; // 字符驱动名字
unsigned int major; // 主设备号
const char *clsname = "mychr"; // 创建class类的名字(不清楚具体什么用途)
struct class *mycls;
struct device *mydev; // read 系统调用
ssize_t demo_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
{
printk(KERN_INFO "kernel read \n");
return ; // 返回读取字节数
} // write 系统调用
ssize_t demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset)
{
printk(KERN_INFO "kernel write \n");
return ;
} // close 系统调用
int demo_release(struct inode *iod, struct file *filp)
{
printk(KERN_INFO "kernel release \n");
return ;
} // open 系统调用
int demo_open(struct inode *iod, struct file *filp)
{
printk(KERN_INFO "kernel open \n");
return ;
}
long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
{
printk(KERN_INFO "kernel ioctl \n");
switch(cmd)
{
case DEMO_CTL_INT0:
printk(KERN_INFO " OPEN LED \n");
break;
case DEMO_CTL_INT1:
printk(KERN_INFO " CLOSE LED \n");
break;
default:
break;
}
return ;
} // 对文件的操作方法集
struct file_operations fops = {
.owner = THIS_MODULE,
.read = demo_read, // 函数实现要在其上面,不然在此处找不到函数的声明
.write = demo_write,
.open = demo_open,
.release = demo_release,
.unlocked_ioctl = demo_ioctl,
}; /* 模块 3 步操作c */ // 模块入口,申请字符设备用到的资源
static int __init demo_init(void)
{
printk(KERN_INFO "module init \n");
// 1. 注册一个字符设备 cdev
major = register_chrdev(, name, &fops); // major=0 表示自动分配主设备号,其返回值是主设备号
if(major <= ){ // 注册字符设备失败
printk(KERN_INFO "register chrdev fail \n");
} // 2.自动创建设备节点 /sys/class 目录下的文件夹名
// 2.1 创建一个 class 类
mycls = class_create(THIS_MODULE, clsname); // 返回值 struct class* 类型
if (IS_ERR(mycls)){ // 创建 class 失败
printk(KERN_INFO "class create fail \n");
unregister_chrdev(major, name); // 在每步检测申请失败了,就要释放前面申请的资源
return PTR_ERR(mycls);
}
// 2.2 创建设备节点的名字
mydev = device_create(mycls, NULL,MKDEV(major, ) , NULL, "demochr%d", ); // 最后 2 个参数会制作这个驱动的可见的名字,安装模块时会看见/dev/demochr0
if (IS_ERR(mydev)) { // 创建设备节点失败
printk(KERN_INFO "failed to create device\n");
unregister_chrdev(major, name);
class_destroy(mycls);
return PTR_ERR(mydev);
}
return ;
} // 模块出口,释放申请的资源
static void __exit demo_exit(void)
{
printk(KERN_INFO "module exit \n");
device_destroy(mycls, MKDEV(major, )); // 上面创建的顺序反向操作,栈操作
class_destroy(mycls);
unregister_chrdev(major, name);
} module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
------demo.h 文件定义的cmd 命令
#ifndef __DEMO_H
#define __DEMO_H #define DEMO_TYPE 's'
#define DEMO_CTL_INT0 _IO(DEMO_TYPE,0)
#define DEMO_CTL_INT1 _IO(DEMO_TYPE,1) #endif // __DEMO_H
-------test.c测试文件
#include <sys/ioctl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "demo.h" const char *pathname = "/dev/demochr0";
int main(int argc, const char *argv[])
{
int fd = open(pathname, O_RDWR);
ioctl(fd,DEMO_CTL_INT1);
ioctl(fd,DEMO_CTL_INT0); return ;
}
----Makfile文件
#KERNELDIR=/lib/modules/3.13.--generic/build
KERNELDIR=/home/linux/share/kernel-3.4. PWD=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
arm-linux-gcc test.c -o test
cp test demo.ko ~/rootfs/home/ clean:
make -C $(KERNELDIR) M=$(PWD) clean
rm test obj-m +=demo.o
烧写到开发板测试:

关于 ioctl 函数的更多相关文章
- (十)Linux 网络编程之ioctl函数
1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...
- IOCTL函数用法
http://blog.163.com/he_junwei/blog/static/19793764620152510533753/ http://blog.csdn.net/styyzxjq2009 ...
- Linux下利用ioctl函数获取网卡信息
linux下的ioctl函数原型如下: #include <sys/ioctl.h> int ioctl(int handle, int cmd, [int *argc, int argv ...
- 文件I/O之ioctl函数
ioctl函数是I/O操作的杂物箱.不能用其他函数表示的I/O操作通常都能用ioctl表示.终端I/O是ioctl的最大使用方面. ioctl函数通过对文件描述符发送特定的命令来控制文件描述符所代表的 ...
- Linux系统编程(4)——文件与IO之ioctl函数
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率.马达的转速等等.它的参数个数如下:int ioctl(int ...
- UNIX网络编程——ioctl 函数的用法详解
1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...
- ioctl函数
一.函数原型 #include <unistd.h> int ioctl(int fd, int request, .../* void *arg */); 二.和网络相关的请求(requ ...
- 六、文件IO——fcntl 函数 和 ioctl 函数
6.1 fcntl 函数 6.1.1 函数介绍 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd ...
- ioctl函数详细说明(网络)
ioctl 函数 本函数影响由fd 参数引用的一个打开的文件. #include<unistd.h> int ioctl( int fd, int request, .../* void ...
- Linux内核的ioctl函数学习
Linux内核的ioctl函数学习 来源:Linux公社 作者:Linux 我这里说的ioctl函数是在驱动程序里的,因为我不知道还有没有别的场合用到了ioctl, 所以就规定了我们讨论的范围.为什 ...
随机推荐
- Django学习笔记--数据库中的单表操作----增删改查
1.Django数据库中的增删改查 1.添加表和字段 # 创建的表的名字为app的名称拼接类名 class User(models.Model): # id字段 自增 是主键 id = models. ...
- 20_1.Condition
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public clas ...
- FreeBSD虚拟机——小折腾
最近,突然想起来Linux了,因为前段时间接触了DOS命令,提高了自己的工作效率,这会想再温习下Linux的CLI,无奈windows下unix命令,水土不服,因此想尝试虚拟机,虚拟机软件无非vmwa ...
- js append()和appendChild()和insertBefore()的区别
<body> <input type="button" value="删除" id="btn"> <scrip ...
- intellij IDEA启动springboot项目报无效的源发行版错误解决方法
从http://start.spring.io/ 上下载的springboot 模板项目,导入intellij 后,报如下错误,原因是intellij 默认使用的Java compiler 是1.8版 ...
- vector内存增长方式
首先必须要了解vector是一种特殊的数组,因此其内存必然是连续的 其次它的连续是建立在不断地对内存的预分配上的,即不断地销毁当前,重新建立内存,效率有点低.所以存在几个函数capacity, siz ...
- signer information does not match signer information of other classes in the same package
报错日志: java.lang.SecurityException: class "org.bouncycastle.asn1.ASN1ObjectIdentifier"'s si ...
- YII 1.0 常用CURD写法
<?php //yii1.0 curd简单写法 //查询 Yii::app()->db->createCommand($sql)->queryAll();//查询所有行数据 ...
- Intel CPUs
http://en.wikipedia.org/wiki/Intel_cpus List of Intel Atom microprocessors List of Intel Xeon microp ...
- 【转】 Linux 命令解释(Linux基础二)
前言 对服务器来讲,图形界面会占用更多的系统资源,而且会安装更多的服务.开放更多的端口,这对服务器的稳定性和安全性都有负面影响.其实,服务器是一个连显示器都没有的家伙,要图形界面干十么? 说到这里,有 ...