open(/dev/ietctl, O_RDWR)  控制…

本文详细解析Linux中使用open函数打开设备文件的过程,包括返回值解释、控制字参数及其作用,并阐述open函数如何与file_operations交互实现对硬件设备的操作。重点突出open函数在硬件文件操作中的核心地位及其实现机制。
open函数,open函数用来打开一个设备,他返回的是一个整型变量,如果这个值等于-1,说明打开文件出现错误,如果为大于0的值,那么这个值代表的就是文件描述符。一般的写法是if((fd=open("/dev/ttys0",O_RDWR | O_NOCTTY | O_NDELAY)<0){
perror("open");
}
这个事常用的一种用法fd是设备描述符,linux在操作硬件设备时,屏蔽了硬件的基本细节,只把硬件当做文件来进行操作,而所有的操作都是以open函数来开始,它用来获取fd,然后后期的其他操作全部控制fd来完成对硬件设备的实际操作。你要打开的/dev/ttyS0,代表的是串口1,也就是常说的com1,后面跟的是一些控制字。int open(const char *pathname, int oflag, …/*, mode_t mode * / ) ;这个就是open函数的公式。控制字可以有多种,我现在给你列出来:
O_RDONLY 只读打开。
O_WRONLY 只写打开。
O_RDWR 读、写打开。
O_APPEND 每次写时都加到文件的尾端。
O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明该新文件的存取许可权位。
O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。这可测试一个文件是否存在,如果不存在则创建此文件成为一个原子操作。
O_TRUNC 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。
O_NOCTTY 如果pathname指的是终端设备,则不将此设备分配作为此进程的控制终端。
O_NONBLOCK 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I / O操作设置非阻塞方式。
O_SYNC 使每次write都等到物理I / O操作完成。
这些控制字都是通过“或”符号分开(|)
当调用系统调用open时,操作系统会将文件系统对应设备文件的inode中的file_operations安装进用户进程的task_struct中的file_struct,然后再调用具体文件的file_operations中的open函数,其他的read、write等等也是如此,所以实际上open操作实际上是一个连接过程,我个人认为称其为open容易误导。至于file_operations中的针对底层硬件的操作,简单地说实际上就是对具体硬件接口的控制/状态寄存器和数据寄存器的读写,如硬盘这种硬件有其自己的控制器,所以他自己内部会定期处理寄存器的命令和数据,完成相应的操作请求,请求完成后cpu发中断
这行代码是使用 Linux 系统调用 `open` 打开一个串口设备文件(这里是 `/dev/ttyS1`),通常用于串口通信(如 RS-232、RS-485 等)。 ```c fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY); ``` --- ### 参数说明: - **`/dev/ttyS1`**: - 表示系统中的第2个串口设备(`ttyS0` 是第一个)。 - 在嵌入式系统或工业通信中,常用于连接串口设备(如 PLC、传感器、RS485 模块等)。 - **`O_RDWR`**: - 以“读写”方式打开设备。 - 可以同时进行读取和写入操作。 - **`O_NOCTTY`**: - 如果打开的是终端设备(如串口),**不将该设备设为控制终端**。 - 避免意外收到 `SIGINT` 等信号影响进程。 - **`O_NDELAY` 或 `O_NONBLOCK`**: - 以“非阻塞”方式打开设备。 - 如果设备暂时没有数据可读或无法立即写入,`read()` 或 `write()` 会立即返回,而不是等待。 - 有些系统中使用 `O_NONBLOCK` 替代。 --- ### 返回值说明: - 成功时返回一个**文件描述符(file descriptor)**,后续用于 `read()`、`write()`、`ioctl()` 等操作。 - 失败时返回 `-1`,并设置 `errno` 错误码。 --- ### 示例:完整打开串口并设置波特率 ```c #include <fcntl.h> #include <unistd.h> #include <termios.h> int setup_serial() { int fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { perror("open"); return -1; } struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B115200); // 设置输入波特率 cfsetospeed(&options, B115200); // 设置输出波特率 options.c_cflag |= (CLOCAL | CREAD); // 启用本地模式和接收功能 options.c_cflag &= ~PARENB; // 无校验 options.c_cflag &= ~CSTOPB; // 1位停止位 options.c_cflag &= ~CSIZE; // 清除数据位掩码 options.c_cflag |= CS8; // 8位数据 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 非规范模式 options.c_oflag &= ~OPOST; // 原始输出 tcsetattr(fd, TCSANOW, &options); // 应用设置 return fd; } ``` --- ### 注意事项: 1. **权限问题**: - 通常需要 root 权限或加入 `dialout` 用户组才能访问串口设备。 - 可通过 `ls -l /dev/ttyS1` 查看权限。 2. **非阻塞 vs 阻塞**: - `O_NDELAY` 或 `O_NONBLOCK` 会影响 `read()` 的行为。 - 若需阻塞等待数据,应去掉该标志。 3. **设备路径**: - `/dev/ttyS0` 是串口0,`/dev/ttyUSB0` 是 USB 转串口设备。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值