Linux 应用开发常用函数速查手册
·
Linux 应用开发常用函数速查手册
一、设备操作基本函数(最常用)
所有 Linux 设备访问都遵循一个套路:
open → read/write → ioctl → close
1. open()
int open(const char *pathname, int flags);
作用:
打开设备 / 文件。
例子:
int fd = open("/dev/led", O_RDWR);
返回:
- 成功 → 文件描述符
fd - 失败 →
-1
驱动对应:
file_operations
.open
2. read()
ssize_t read(int fd, void *buf, size_t count);
作用:
从设备读取数据。
例子:
char buf[10];
read(fd, buf, sizeof(buf));
驱动对应:
file_operations
.read
3. write()
ssize_t write(int fd, const void *buf, size_t count);
作用:
向设备写数据。
例子:
write(fd, "1", 1);
驱动对应:
file_operations
.write
4. ioctl()
int ioctl(int fd, unsigned long cmd, unsigned long arg);
作用:
发送 控制命令。
例子:
ioctl(fd, LED_ON);
驱动对应:
file_operations
.unlocked_ioctl
5. close()
int close(int fd);
作用:
关闭设备。
例子:
close(fd);
驱动对应:
file_operations
.release
二、I/O 多路复用函数(重点)
当你看到:
应用程序使用
select()、poll()或epoll()
其实就是 等待多个设备同时有数据。
比如:
- 键盘
- socket
- 触摸屏
- 管道
1. select()
最早的多路复用函数。
int select(int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout);
例子:
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
select(fd+1, &rfds, NULL, NULL, NULL);
if (FD_ISSET(fd, &rfds))
{
read(fd, buf, sizeof(buf));
}
特点:
- 最老
- 最大 1024 fd
- 效率低
2. poll()
比 select 更现代。
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
例子:
struct pollfd fds;
fds.fd = fd;
fds.events = POLLIN;
poll(&fds, 1, -1);
if (fds.revents & POLLIN)
{
read(fd, buf, sizeof(buf));
}
特点:
- 没有 1024 限制
- 内核遍历
3. epoll()
Linux 最强 I/O 模型。
epoll_create()
epoll_ctl()
epoll_wait()
例子:
int epfd = epoll_create(1);
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
epoll_wait(epfd, events, 10, -1);
特点:
- 高并发服务器
- nginx / redis 使用
三、三者对比(面试常问)
| 函数 | 最大连接 | 效率 | 使用场景 |
|---|---|---|---|
| select | 1024 | 低 | 简单程序 |
| poll | 无限制 | 中 | 普通程序 |
| epoll | 无限制 | 高 | 服务器 |
一句话记忆:
select → 老
poll → 改进
epoll → 高并发
四、驱动里对应函数(非常关键)
当应用调用这些函数时,驱动会进入:
| 应用函数 | 驱动函数 |
|---|---|
| open | .open |
| read | .read |
| write | .write |
| ioctl | .unlocked_ioctl |
| poll/select | .poll |
| close | .release |
例如:
struct file_operations my_fops = {
.open = my_open,
.read = my_read,
.write = my_write,
.poll = my_poll,
};
五、阻塞 vs 非阻塞 IO
很多驱动教程都会写:
阻塞IO
非阻塞IO
例子:
阻塞:
read(fd, buf, 10);
如果没有数据:
程序卡住等待
非阻塞:
open("/dev/test", O_NONBLOCK);
如果没数据:
立即返回
六、驱动里如何支持 select/poll
驱动要实现:
.poll
例子:
unsigned int my_poll(struct file *file, poll_table *wait)
{
poll_wait(file, &wait_queue, wait);
if(data_ready)
return POLLIN;
return 0;
}
作用:
告诉内核:
设备有没有数据
七、给你一个最简单完整程序
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
char buf[10];
fd = open("/dev/test", O_RDWR);
read(fd, buf, sizeof(buf));
write(fd, "1", 1);
close(fd);
return 0;
}
流程:
open → read → write → close
八、真正的高手学习方法(非常重要)
不要死记函数,而是记 套路:
Linux 应用基本只有 5 件事:
open
read
write
ioctl
poll
90%程序都是:
打开设备
等待数据
读取数据
处理数据
更多推荐

所有评论(0)