新人学习,欢迎指正

部分select.c代码

		    应用层
select(maxfd+1,&rfds,NULL,NULL,NULL);
-------------------(系统调用)------------------------------
kernel-3.4.39/arch/arm/kernel$ vi calls.S
//系统调用相关的汇编文件
CALL(sys_select)
VFS:vi -t sys_select ->SYSCALL_DEFINE5宏,5代表有五个参数,替换得到sys_select
SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp,\
fd_set __user *, outp,fd_set __user *, exp, \
struct timeval __user *, tvp)
->
#define SYSCALL_DEFINE5(select, ...)
SYSCALL_DEFINEx(5, _select, __VA_ARGS__)
->
#define SYSCALL_DEFINEx(x,_select, ...)
__SYSCALL_DEFINEx(x, _select, __VA_ARGS__)
->
#define __SYSCALL_DEFINEx(x, _select, ...) long sys_select(int n, fd_set __user * inp,
fd_set __user *outp,fd_set __user *exp,
struct timeval __user * tvp)
{ ret = core_sys_select(n, inp, outp, exp, to);
}
--------------------------------------------------------------
core_sys_select(n, inp, outp, exp, to);
//1.校验最大的文件描述符
struct fdtable *fdt;
fdt = files_fdtable(current->files);
max_fds = fdt->max_fds;
if (n > max_fds)
n = max_fds; //2.分配文件描述符的内存
bits = kmalloc(6 * size, GFP_KERNEL);
fds.in = bits;
fds.out = bits + size;
fds.ex = bits + 2*size;
//在内核空间分配的读表,写表,其他表的首地址
fds.res_in = bits + 3*size;
fds.res_out = bits + 4*size;
fds.res_ex = bits + 5*size;
//在内核空间分配的准备好的读表,写表,其他表的首地址 //3.将用户空间的读表,写表,其他的表拷贝到内核空间
if ((ret = get_fd_set(n, inp, fds.in)) ===>copy_from_user
(ret = get_fd_set(n, outp, fds.out))
(ret = get_fd_set(n, exp, fds.ex))) //4.文件描述符的检查,如果所有的文件描述符的数据
都没有准备好,进程休眠,否则将准备好的文件描
述符放入到fds.res_in,fds.res_out,fds.res_ex
ret = do_select(n, &fds, end_time); //5.判断是否是信号唤醒的进程
ret = -ERESTARTNOHAND;
if (signal_pending(current))
goto out; ====>信号唤醒的就跳过拷贝
ret = 0;
//6.如果不是信号唤醒的休眠,将文件描述符拷贝到用户空间
if (set_fd_set(n, inp, fds.res_in) ||
set_fd_set(n, outp, fds.res_out) || ====>copy_to_user
set_fd_set(n, exp, fds.res_ex))
ret = -EFAULT;
---------------------------------------------------------------------
驱动:
unsigned int (*poll) (struct file *file,\
struct poll_table_struct *wait);

部分do_select代码

int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
{ struct poll_wqueues table;
poll_table *wait;
int retval, i;
unsigned long slack = 0; retval = max_select_fd(n, fds);
//通过文件描述符表中的对应的被设置
//为1的位来校验最大的文件描述符的值 n = retval;
//将校验完的文件描述符赋值给n poll_initwait(&table);
//poll相关结构体的初始化
//只需要关心函数指针的初始化过程就行了
//函数指针,执行的是__pollwait
//在__pollwait会拿到你提交的等待队列头,然后
//在等待队列头后面添加当前进程的等待队列项 retval = 0;
//retval是用来判断是否需要退出文件描述符遍历
//的循环的。 for (;;)
{
unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; inp = fds->in;
outp = fds->out;
exp = fds->ex;
rinp = fds->res_in;
routp = fds->res_out;
rexp = fds->res_ex;
//定义6个指针,将结构体中的6个指针
//赋值给这6个指针变量 for (i = 0; i < n; ++rinp, ++routp, ++rexp)
{
//用来取第几个unsigned long类型的数据
unsigned long in, out, ex, all_bits, bit = 1, mask, j;
unsigned long res_in = 0, res_out = 0, res_ex = 0;
const struct file_operations *f_op = NULL;
struct file *file = NULL; in = *inp++;
out = *outp++;
ex = *exp++;
all_bits = in | out | ex;
if (all_bits == 0)
{
i += BITS_PER_LONG;
continue;
} for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1)
{
//用来unsigned long类型中的第几位的 file = fget_light(i, &fput_needed);
//这里的i就是获取到的文件描述符,fget_light
//通过文件描述符找到file结构体
//fd->fd_array[fd]->struct file
//POLLIN if (file)
{
f_op = file->f_op;
if (f_op && f_op->poll)
{
mask = (*f_op->poll)(file, wait);
}
//如果file存在,并且fops存在,并且fops中的
//poll函数存在,就调用这个存在的poll函数
//就会得到mask
if ((mask & POLLIN_SET) && (in & bit))
{
res_in |= bit;
//将当前的文件描述符放到
//要返回的文件描述符表中
retval++;
} if ((mask & POLLOUT_SET) && (out & bit))
{
res_out |= bit;
retval++;
}
if ((mask & POLLEX_SET) && (ex & bit))
{
res_ex |= bit;
retval++;
}
//如果mask中的POLLIN/POLLOUT/POLLEX被置位了
//将这些文件描述符放到准备好的文件描述表中
//并且将retval这个变量加1,只要retval不为0,
//死循环就会被退出
}
}
} if (retval || timed_out || signal_pending(current))
break;
//如果retval不为0,或者超时时间到了或者信号到来了
//这个死循环就会被退出 if (!poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,
to, slack))
//如果上述的条件都不满足,循环没有退出,进程
//就进入休眠状态
} return retval;
} }

驱动IO模型-select的更多相关文章

  1. Linux 网络编程的5种IO模型:信号驱动IO模型

    Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...

  2. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  3. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

  4. 几种服务器端IO模型的简单介绍及实现

    一些概念: 同步和异步 同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发I/O操作并等待或者轮询的去查看I/O操作是否就绪,而异步是指用户进程触发I/O操作以后便开始做自己的事情,而 ...

  5. JAVA基础知识之网络编程——-网络通信模型(IO模型)

    <Unix网络编程:卷1>中介绍了5中I/O模型,JAVA作为运行在宿主机上的程序,底层也遵循这5中I/O模型规则.这5中I/O模型分别是: 阻塞式IO 非阻塞式IO I/O复用 信号驱动 ...

  6. Linux Network IO Model、Socket IO Model - select、poll、epoll

    目录 . 引言 . IO机制简介 . 阻塞式IO模型(blocking IO model) . 非阻塞式IO模型(noblocking IO model) . IO复用式IO模型(IO multipl ...

  7. linux第7天 I/O的五种模型, select

    服务器端避免僵尸进程的方法: 1)通过忽略SIGCHLD信号,解决僵尸进程 signal(SIGCHLD, SIG_IGN) 2)通过wait方法,解决僵尸进程 signal(SIGCHLD, han ...

  8. 浅析IO模型

    也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗.在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型.下面本文先从同步和异步的概念 说起, ...

  9. IO模型分析

    html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...

随机推荐

  1. [TensorFlow2.0]-Fashion-MNIST本地数据集及fit_generator()的使用

    本人人工智能初学者,现在在学习TensorFlow2.0,对一些学习内容做一下笔记.笔记中,有些内容理解可能较为肤浅.有偏差等,各位在阅读时如有发现问题,请评论或者邮箱(右侧边栏有邮箱地址)提醒. 若 ...

  2. MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用

    转载自 MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用 LambdaQueryWrapper https://blog.csdn.net/lt32603 ...

  3. python3+telnetlib实现简单自动测试

    1 telnetlib介绍 1.1 简介 官方介绍文档:telnetlib -- Telnet 客户端 - Python 3.9.6 文档 telnetlib 模块提供一个实现Telnet协议的类 T ...

  4. Linux下库的制作(静态库与共享库)

    库中实际上就是已编译好的函数代码,可以被程序直接调用. Linux下的库一般的位置在/lib或者/usr/lib中 静态库 静态库是复制拷贝到调用函数中的,函数运行的时候不再需要静态库,因为静态库是在 ...

  5. Android模块化开发实践

    一.前言 随着业务的快速发展,现在的互联网App越来越大,为了提高团队开发效率,模块化开发已经成为主流的开发模式.正好最近完成了vivo官网App业务模块化改造的工作,所以本文就对模块化开发模式进行一 ...

  6. CycliBarriar和CountdownLatch(计数器)

    CyclicBarrier可以重复使用,而CountdownLatch不能重复使用. countDownLatch这个类使一个线程等待其他线程各自执行完毕再执行. 是通过一个计数器来实现的,计数器的初 ...

  7. docker harbor安装

    # 官网下载离线包,https://github.com/goharbor/harbor/releases src]# tar xf harbor-offline-installer-v1.8.3.t ...

  8. AECC2018同时中英文切换多开使用,加倍提高你的工作效率

    最近相信不少人已经更新了AECC2018,升级之后第一件重要的事当然是中英文的切换了,要不然工作中很麻烦.对于一直习惯用中文的人来说,在用模板过程中会出现各种表达式报错极其不方便,而对于习惯英文操作朋 ...

  9. RabbitMQ(二):交换机

    前言 学习自bili尚硅谷-RabbitMQ 发布确认 之前的消息应答,队列持久化是为了保证 -> 消息从rabbitmq队列到消费者的过程中不会丢失:消息持久化则是为了保证 -> 消息从 ...

  10. WebStorm 2018.3.2 激活方式(永久)

    其他版本下载:https://www.jetbrains.com/webstorm/download/other.html 这个适合2018.3.2 第一步:下载补丁包(jar)链接:https:// ...