linux使用open无法打开驱动解决方式

本文介绍了一个简单的字符设备驱动实例,探讨了使用静态与动态设备号的区别。通过动态分配设备号和创建设备文件,解决了无法打开及访问驱动的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  最近测试自己写的字符设备驱动例子(这里以test.ko为实例), 用户层多次调用open("/dev/test",O_RDWR)返回值为-1,根据返回状态捕获到错误(“No such device or address”),偶尔打开字符设备驱动也无法访问驱动函数(比如ioctl函数返回值是-1) 。后来改用动态分配设备号,代码内动态创建设备描述文件(/dev/test)后每次都可以成功open,并且可以成功调用驱动实现的ioctl、read以及write等函数。

  根据此方式编写一个简单的字符设备驱动以及用户层打开实例,以供参考:

//测试驱动实例
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/device.h>

#define DevName "test"
#define ClassName "class_test"

struct class    *mem_class;
struct Pci_dev  *test_devices;
struct cdev 	_cdev;
dev_t    dev;

static int Test_open(struct inode *inode,struct file *filp)
{
	return 0;
}

static int Test_release(struct inode *inode,struct file *filp)
{
	return 0;
}

//这里只添加了open、release函数,如果需要用到ioctl函数在file_operations描述项里添加即可
static struct file_operations test_fops = {
.owner = THIS_MODULE,
//.ioctl = Test_ioctl,
.open = Test_open,
.release = Test_release,
};
static int Test_init_module(void)//驱动入口函数
{	
	//动态分配设备号
	int result = alloc_chrdev_region(&dev, 0, 2, DevName);
	if (result < 0)
	{
		printk("Err:failed in alloc_chrdev_region!\n");
		return result;
	}
	//创建class实例
	mem_class = class_create(THIS_MODULE,ClassName);// /dev/ create devfile 
    	if (IS_ERR(mem_class))
    	{
		printk("Err:failed in creating class!\n");
  	}
  	//动态创建设备描述文件 /dev/test
	device_create(mem_class,NULL,dev,NULL,DevName);

	cdev_init(&_cdev,&test_fops);
	_cdev.owner = THIS_MODULE;
	_cdev.ops = &test_fops;//Create Dev and file_operations Connected
	result = cdev_add(&_cdev,dev,1);
	return result;
}

static void Test_exit_module(void)//驱动退出函数
{
	if (0 != mem_class)
    	{
		device_destroy(mem_class,dev);
		class_destroy(mem_class);
		mem_class = 0;
    	}
	cdev_del(&_cdev);
}
module_init(Test_init_module);
module_exit(Test_exit_module);
MODULE_AUTHOR(DevName);
MODULE_LICENSE("GPL");

  用户层:

首先 sudo chmod 777(或666)/dev/test 修改文件访问权限,

int fd;
fd=open("/dev/test",O_RDWR);//打开驱动

  返回值:
这里写图片描述

  到这里字符设备驱动可以正常访问了,之后可以根据驱动需要的功能增加相应的函数!

<think>我们正在讨论Linuxopen系统调用打开文件的方式open函数用于打开或创建一个文件,并返回文件描述符。 常用的打开方式包括只读、只写、读写等,以及一些标志如O_CREAT、O_APPEND等。 我们将列举常见的打开方式(flags)并解释其含义。 注意:open有两种原型,一种是两个参数(当不创建新文件时),另一种是三个参数(当需要创建文件时,需指定文件权限)。 我们将重点放在flags参数上。</think>在Linux系统中,`open()`系统调用用于打开文件,其函数原型为: ```c #include <fcntl.h> int open(const char *pathname, int flags, mode_t mode); // mode可选 ``` ### 核心打开方式(flags参数组合) | 标志组合 | 等效函数 | 描述 | |---------|---------|------| | `O_RDONLY` | - | 只读打开 | | `O_WRONLY` | - | 只写打开 | | `O_RDWR` | - | 读写打开 | | `O_CREAT \| O_WRONLY` | `creat()` | 创建文件(需指定mode) | | `O_APPEND \| O_WRONLY` | - | 追加写入(原子操作) | | `O_TRUNC \| O_WRONLY` | - | 清空文件后写入 | ### 关键标志位详解 1. **基础访问模式**(互斥): - `O_RDONLY`:只读 (值为0) - `O_WRONLY`:只写 (值为1) - `O_RDWR`:读写 (值为2) 2. **创建与截断**: - `O_CREAT`:文件不存在时创建(需配合`mode`参数) - `O_EXCL`:与`O_CREAT`联用,文件存在则报错(防竞争) - `O_TRUNC`:打开时清空文件(需有写权限) 3. **写入控制**: - `O_APPEND`:每次写入追加到文件末尾(原子操作) - `O_DSYNC`:数据同步写入(等待物理存储) - `O_SYNC`:数据+元数据同步写入 4. **非阻塞与路径**: - `O_NONBLOCK`:非阻塞模式(用于FIFO/套接字) - `O_NOFOLLOW`:不追踪符号链接(防链接攻击) - `O_DIRECTORY`:要求路径必须是目录 5. **异步I/O**: - `O_ASYNC`:启用信号驱动I/O(如SIGIO) ### 权限模式(mode参数) 当使用`O_CREAT`时必须指定,常用值: - `S_IRUSR` (0400):用户可读 - `S_IWUSR` (0200):用户可写 - `S_IXUSR` (0100):用户可执行 - `S_IRGRP` (0040):组可读 - `S_IROTH` (0004):其他可读 ### 使用示例 ```c // 只读打开文件 int fd1 = open("file.txt", O_RDONLY); // 创建新文件(用户读写,组读) int fd2 = open("new.log", O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP); // 追加写入(非阻塞) int fd3 = open("access.log", O_WRONLY | O_APPEND | O_NONBLOCK); ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坤昱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值