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%程序都是:

打开设备
等待数据
读取数据
处理数据
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐