ioctrl原形 linux_Linux ioctl 从应用到驱动

本文介绍了Linux ioctl从应用到驱动的实现。在驱动方面,需复制示例代码到指定目录,修改相关文件,定义ioctl命令、实现ioctl函数、定义file_operations并注册设备;在应用程序方面,若为Android工程,复制代码到指定目录并编译,还给出了使用ioctl的示例代码。

Linux ioctl 从应用到驱动

驱动

将示例代码中n76e003_driver复制到linux/drivers/misc目录下,修改相关Kconfig与Makefile文件

头文件中定义ioctl命令

// ioctl cmd

#define N76E003_IOC_MAGIC 'k'

#define N76E003_IOC_HEARTBEAT _IO(N76E003_IOC_MAGIC, 1)

#define N76E003_IOC_SET_UPTIME _IOW(N76E003_IOC_MAGIC, 2, int)

#define N76E003_IOC_MAXNR 2

struct n76e003_data {

struct i2c_client *client;

struct miscdevice n76e003_device;

};

实现ioctl函数

static int n76e003_dev_open(struct inode *inode, struct file *filp)

{

int ret = 0;

struct n76e003_data *n76e003 = container_of(filp->private_data,

struct n76e003_data,

n76e003_device);

filp->private_data = n76e003;

dev_info(&n76e003->client->dev,

"device node major=%d, minor=%d\n", imajor(inode), iminor(inode));

return ret;

}

static long n76e003_dev_ioctl(struct file *pfile,

unsigned int cmd, unsigned long arg)

{

int ret = 0;

int data = 0;

struct n76e003_data *n76e003 = pfile->private_data;

if (_IOC_TYPE(cmd) != N76E003_IOC_MAGIC)

return -EINVAL;

if (_IOC_NR(cmd) > N76E003_IOC_MAXNR)

return -EINVAL;

if (_IOC_DIR(cmd) & _IOC_READ)

ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));

else if (_IOC_DIR(cmd) & _IOC_WRITE)

ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));

if (ret)

return -EFAULT;

dev_info(&n76e003->client->dev,

"%s, (%x, %lx):\n", __func__, cmd,

arg);

switch (cmd) {

case N76E003_IOC_HEARTBEAT:

n76e003_heartbeat(n76e003->client);

break;

case N76E003_IOC_SET_UPTIME:

if (copy_from_user(&data, (int *)arg, sizeof(int))) {

dev_err(&n76e003->client->dev,

"%s, copy from user failed\n", __func__);

return -EFAULT;

}

n76e003_set_uptime(n76e003->client, data);

break;

default:

return -EINVAL;

}

return 0;

}

定义file_operations

static const struct file_operations n76e003_dev_fops = {

.owner = THIS_MODULE,

.open = n76e003_dev_open,

.unlocked_ioctl = n76e003_dev_ioctl

};

注册设备

static int n76e003_probe(struct i2c_client * client, const struct i2c_device_id * id)

{

...

n76e003->n76e003_device.minor = MISC_DYNAMIC_MINOR;

n76e003->n76e003_device.name = "n76e003";

n76e003->n76e003_device.fops = &n76e003_dev_fops;

ret = misc_register(&n76e003->n76e003_device);

if (ret) {

dev_err(&client->dev, "Failed misc_register\n");

goto exit_misc_register;

}

...

}

应用程序

如果是Android工程,将示例代码中n76e003_app复制到external目录下,并在Android根目录执行:make n76e003

#include

#include

#include

#include

#include

#define DEV_NAME "/dev/n76e003"

// ioctl cmd

#define N76E003_IOC_MAGIC 'k'

#define N76E003_IOC_HEARTBEAT _IO(N76E003_IOC_MAGIC, 1)

#define N76E003_IOC_SET_UPTIME _IOW(N76E003_IOC_MAGIC, 2, int)

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

{

int ret, fd, num, arg;

fd = open(DEV_NAME, O_RDWR);

if (fd < 0) {

printf("Open device fail!\n");

return -1;

}

/*

read(fd, &num, sizeof(int));

printf("The num is: %d\n", num);

printf("Please input a number written to testdriver: \n");

scanf("%d", &num);

write(fd, &num, sizeof(int));

read(fd, &num, sizeof(int));

printf("The num is: %d\n", num);

*/

arg = 0xff;

ret = ioctl(fd, N76E003_IOC_HEARTBEAT, &arg);

if (ret < 0) {

printf("ioctl: %d\n", ret);

}

sleep(10);

arg = 0x01020304;

ret = ioctl(fd, N76E003_IOC_SET_UPTIME, &arg);

if (ret < 0) {

printf("ioctl: %d\n", ret);

}

close(fd);

return 0;

}

由于没有提供具体的`uds_ioctrl_t ioctrl_list`数组定义及元素初始化的代码,下面进行一般性的分析。 ### 数组定义的含义 在C语言中,`uds_ioctrl_t ioctrl_list[size];`这样的语句定义了一个名为`ioctrl_list`的数组,数组的元素类型为`uds_ioctrl_t`。这里的`uds_ioctrl_t`应该是一个自定义的数据类型,可能是结构体、枚举或者联合体等。例如,如果`uds_ioctrl_t`是一个结构体类型: ```c typedef struct { int param1; float param2; char *param3; } uds_ioctrl_t; uds_ioctrl_t ioctrl_list[10]; ``` 上述代码定义了一个包含10个`uds_ioctrl_t`类型元素的数组。 ### 元素初始化的含义和用途 元素初始化是在定义数组时为数组中的元素赋予初始值。初始化的方式有多种,以下是不同情况的分析: #### 部分初始化 ```c uds_ioctrl_t ioctrl_list[10] = { {1, 2.0, "str1"}, {2, 3.0, "str2"} }; ``` 这种情况下,数组的前两个元素被显式初始化,其余元素会根据`uds_ioctrl_t`的类型进行默认初始化。如果`uds_ioctrl_t`是结构体,未显式初始化的成员会被初始化为0(对于数值类型)或`NULL`(对于指针类型)。 #### 全部初始化 ```c uds_ioctrl_t ioctrl_list[2] = { {1, 2.0, "str1"}, {2, 3.0, "str2"} }; ``` 这里数组的所有元素都被显式初始化,每个元素都有明确的初始值。 #### 用途 - **数据存储**:数组可以用来存储一组相关的数据。例如,`uds_ioctrl_t`可能表示一组控制参数,`ioctrl_list`数组可以存储多个这样的控制参数集合,方便对这些参数进行统一管理和操作。 - **循环处理**:可以使用循环遍历数组中的元素,对每个元素进行相同或相似的操作。例如: ```c for (int i = 0; i < 10; i++) { // 对ioctrl_list[i]进行操作 printf("param1: %d\n", ioctrl_list[i].param1); } ``` ### 结合引用内容推测 在引用内容中提到了UDF(用户自定义函数)和UDS(用户自定义标量)相关的宏。`uds_ioctrl_t`可能是与UDS控制相关的数据类型,`ioctrl_list`数组可能用于存储UDS的控制信息,例如扩散系数、对流项参数等。在UDF中,这些信息可以用于控制非稳态和对流项的计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值