Linux 内核机制--阻塞与非阻塞机制及Poll/Select分析

多路IO(三)——poll机制 多路IO之poll机制 poll函数 1.函数原型 #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); 2.功能 监听集合有没有动静,如果没有动静就阻塞 如果有动静就成功返回,返回值为集合中有动静的fd的数量 3.参数 fds:这个参数写为struct pollfd fds[]更好理解些,第一个参数要求传递一个struct pollfd结构体数组。 这个数组就相当于select 阅读详情
阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时,并不挂起。被挂起的进程进入sleep状态,被从调度器的运行队列移走,直到等待的条件被满足。 

在Linux驱动程序中,我们可以使用等待队列(wait queue)来实现阻塞操作。wait queue很早就作为一个基本的功能单位出现在Linux内核里了,它以队列为基础数据结构,与进程调度机制紧密结合,能够用于实现核心的异步事件通知机制。等待队列可以用来同步对系统资源的访问,上节中所讲述Linux信号量在内核中也是由等待队列来实现的。 

下面我们以"globalfifo"为例,来说明linux下poll/select及阻塞与非阻塞操作的实现过程."globalfifo"可以被多个进程打开,但是每次只有当一个进程写入了一个数据之后本进程或其它进程才可以读取该数据,否则一直阻塞。

select和 poll的本质一样,前者在BSD Unix中引入,后者在System V中引入。poll和select用于查询设备的状态,以便用户程序获知是否能对设备进行非阻塞的访问,它们都需要设备驱动程序中的poll函数支持。

驱动程序中poll函数中最主要用到的一个API是poll_wait,其原型如下:

void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table * wait);

poll_wait函数所做的工作是把当前进程添加到wait参数指定的等待列表(poll_table)中。工作过程如下图所示:

下面我们给出globalfifo的poll函数:

static unsigned int globalfifo_poll(struct file *filp, poll_table *wait)

{
  unsigned int mask = 0;
  struct globalfifo_dev *dev = filp->private_data; /*获得设备结构体指针*/
  
  down(&dev->sem);


  //添加等待队列
dev->r_wait/dev->w_wait到poll_table wait所在的结构体的poll_table_entry中,然后添加等待队列项(指向当前进程)到等待队列头dev->r_wait/dev->w_wait中
  poll_wait(filp, &dev->r_wait, wait);
  poll_wait(filp, &dev->w_wait, wait);  


  /*fifo非空*/
  if (dev->current_len != 0)
  {
    mask |= POLLIN | POLLRDNORM; /*标示数据可获得*/
  }
  /*fifo非满*/
  if (dev->current_len != GLOBALFIFO_SIZE)
  {
    mask |= POLLOUT | POLLWRNORM; /*标示数据可写入*/
  }
     
  up(&dev->sem);
  return mask;
}

poll_wait内核实现代码如下:
static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
                poll_table *p)
{
    struct poll_table_entry *entry = poll_get_entry(p);
    if (!entry)
        return;
    get_file(filp);
    entry->filp = filp;
    entry->wait_address = wait_address;//添加wait_queue_head_t到entry
    init_waitqueue_entry(&entry->wait, current);
    add_wait_queue(wait_address, &entry->wait);//添加等待队列项到等待队列头
}

poll_wait函数并不阻塞,真正的阻塞动作是上层的select/poll函数中完成的。select/poll会在一个循环中对每个需要监听的设备调用它们自己的poll支持函数以使得当前进程被加入各个设备的等待列表。若当前没有任何被监听的设备就绪,则内核进行调度(调用schedule)让出cpu进入阻塞状态,schedule返回时将再次循环检测是否有操作可以进行,如此反复;否则,若有任意一个设备就绪, select/poll都立即返回。以select(2.6.28内核)为例代码如下:

SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
        fd_set __user *, exp, struct timeval __user *, tvp)
{
    struct timespec end_time, *to = NULL;
    struct timeval tv;
    int ret;

    if (tvp) {
        if (copy_from_user(&tv, tvp, sizeof(tv)))
            return -EFAULT;

        to = &end_time;
        if (poll_select_set_timeout(to,
                tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
                (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
            return -EINVAL;
    }

    ret = core_sys_select(n, inp, outp, exp, to);
    ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);

    return ret;
}
poll/select内核调用过程如下: select()-> core_sys_select ()->do_select():do_select的源代码如下:
int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
{
    ktime_t expire, *to = NULL;
    struct poll_wqueues table;
    poll_table *wait;
    int retval, i, timed_out = 0;
    unsigned long slack = 0;

    rcu_read_lock();
    retval = max_select_fd(n, fds);
    rcu_read_unlock();

    if (retval < 0)
        return retval;
    n = retval;

    
poll_initwait(&table);//初始化结构体,主要是初始化poll_wait的回调函数为__pollwait
    wait = &table.pt;

    if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
        wait = NULL;
        timed_out = 1;
    }

    if (end_time && !timed_out)
        slack = estimate_accuracy(end_time);

    retval = 0;
    for (;;) {
        unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;

        set_current_state(TASK_INTERRUPTIBLE);//设置当前进程状态为
TASK_INTERRUPTIBLE

        inp = fds->in; outp = fds->out; exp = fds->ex;
        rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;

        for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
            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 += __NFDBITS;
                continue;
            }

            for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
                int fput_needed;
                if (i >= n)
                    break;
                if (!(bit & all_bits))
                    continue;
                file = fget_light(i, &fput_needed);
                if (file) {
                    f_op = file->f_op;
                    mask = DEFAULT_POLLMASK;
                    if (f_op && f_op->poll)
                        mask = (*f_op->poll)(file, retval ? NULL : wait);
//调用poll_wait处理过程,即把驱动中等待队列头增加到poll_wqueues中的entry中,并把指向当前里程的等待队列项增加到等待队列头中。每一个等待队列头占用一个entry
                    fput_light(file, fput_needed);
                    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++;
                    }
                }
            }
            if (res_in)
                *rinp = res_in;
            if (res_out)
                *routp = res_out;
            if (res_ex)
                *rexp = res_ex;
            
cond_resched();//增加抢占点,调度其它进程,当前里程进入睡眠
        }
        wait = NULL;
        if (retval || timed_out || signal_pending(current))
            break;
        if (table.error) {
            retval = table.error;
            break;
        }

        /*
         * If this is the first loop and we have a timeout
         * given, then we convert to ktime_t and set the to
         * pointer to the expiry value.
         */
        if (end_time && !to) {
            expire = timespec_to_ktime(*end_time);
            to = &expire;
        }

        if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
            timed_out = 1;
    }
    __set_current_state(TASK_RUNNING);

    
poll_freewait(&table);//从等待队列头中删除poll_wait中添加的等待队列,并释放资源

    return retval;
}
从以上代码可以看出,当一个想从设备读数据的进程调用select,则内核调用poll_wait,把含当前进程的等待队列项添加到设备的等待列队上,然后简单的把当前里程设置为睡眠。直到有其它进程写设备,数据可获取,调用wake up,唤醒当前进程。当前进程继续执行,再次调用poll后,有数据可读返回。
下面再看globalfifo的write过程,源代码如下:
/*globalfifo写操作*/
static ssize_t globalfifo_write(struct file *filp, const char __user *buf,
  size_t count, loff_t *ppos)
{
  struct globalfifo_dev *dev = filp->private_data; //获得设备结构体指针
  int ret;
  DECLARE_WAITQUEUE(wait, current); //定义等待队列

  down(&dev->sem); //获取信号量
  add_wait_queue(&dev->w_wait, &wait); //进入写等待队列头

  /* 等待FIFO非满 */
  if (dev->current_len == GLOBALFIFO_SIZE)
  {
    if (filp->f_flags &O_NONBLOCK)
    //如果是非阻塞访问
    {
      ret =  - EAGAIN;
      goto out;
    } 
    __set_current_state(TASK_INTERRUPTIBLE); //改变进程状态为睡眠
    up(&dev->sem);

    schedule(); //调度其他进程执行
    if (signal_pending(current))
    //如果是因为信号唤醒
    {
      ret =  - ERESTARTSYS;
      goto out2;
    }

    down(&dev->sem); //获得信号量
  }

  /*从用户空间拷贝到内核空间*/
  if (count > GLOBALFIFO_SIZE - dev->current_len)
    count = GLOBALFIFO_SIZE - dev->current_len;

  if (copy_from_user(dev->mem + dev->current_len, buf, count))
  {
    ret =  - EFAULT;
    goto out;
  }
  else
  {
    dev->current_len += count;
    printk(KERN_INFO "written %d bytes(s),current_len:%d\n", count, dev
      ->current_len);

    wake_up_interruptible(&dev->r_wait); //唤醒读等待队列,睡眠在读队列上的里程被唤醒。
    
    ret = count;
  }

  out: up(&dev->sem); //释放信号量
  out2:remove_wait_queue(&dev->w_wait, &wait); //从附属的等待队列头移除
  set_current_state(TASK_RUNNING);
  return ret;
}
读函数的阻塞机制同上,这里就不再详述。
Linux高级字符设备:Poll操作 在用户程序中,select()和poll()也是与设备阻塞与非阻塞访问息息相关的,使用非阻塞I/O的应用程序通常会使用select和poll系统调用查询是否可对设备进行无阻塞的访问。(1)对可能引起设备文件状态变化的等待队列调用poll_wait()函数,将对应等待队列添加到poll_table中;2)如果当前不可读写,则阻塞进程,并等待驱动程序唤醒,重新调用poll函数,或超时返回。2、核心层调用sys_select() ------> do_select()(1)将要监控的文件添加到文件描述符集; 阅读详情

相关推荐

LangGraph实战:用Python异步构建智能客服多轮对话系统(附完整代码)

本文详细介绍了如何使用LangGraph框架和Python异步编程构建一个高性能的智能客服多轮对话系统。通过将对话流程建模为有向图,结合thread_id实现多用户对话隔离,并利用异步节点提升系统并发处理能力,有效解决了传统客服系统上下文遗忘与高并发瓶颈问题。文章提供了从环境搭建、状态管理、异步优化到复杂业务逻辑与部署的完整实战代码。

weixin_29055137的博客 149

poll_wait函数详解

原文地址 http://www.cnblogs.com/hanyan225/archive/2010/10/13/1850497.html “小王,来聊聊,今天面试的情况怎么样,应该挺顺利的吧..”看着小王平淡的眉头,我问道。 “唉,别提了,你说,我的运气咋这差呢,面试前你不是给我讲了有关阻塞的问题吗,我见了面试官是吧,还跟他好好的用今天排队的例子说了有关阻塞的问题,但是.

1万+

基于RK3562J开发板的MCP2518FD CAN-FD控制器驱动适配与测试指南

本文详细介绍了在RK3562J开发板上适配MCP2518FD CAN-FD控制器驱动的完整流程。内容涵盖内核驱动配置、设备树修改、编译烧录以及实际通信测试,重点分享了调试方法,旨在帮助开发者快速为嵌入式系统扩展高速CAN-FD通信能力,适用于汽车电子、工业控制等场景。

jenkins8butler的博客 495

linux的poll_wait函数,等待队列和poll机制

在Linux驱动程序中可以用等待队列来实现阻塞进程的唤醒,并能用等待队列来是实现内核中的异步事件通知机制。初始化等待队列:利用宏:DECLARE_WAIT_QUEUE_HEAD(button_queue);//定义并初始化一个名为button_queue的等待队列(等待队列的定义和初始化有具体的函数,这个宏也是替换成或调用哪些函数)。等待事件:wait_event(queue);wait_even...

weixin_32799203的博客 7264

25个Prompt去除AI味,让AI写作更像真人

自然语言生成技术飞速发展,如今AI写作已经深度融入内容创作、营销运营和日常办公。但许多用户发现,AI生成的文本常常带着一股“AI味”——句子过于工整、过度总结、细节空洞,导致内容被一眼识破,甚至面临“AI率”过高的尴尬。其实,这种塑料感源于大模型的训练数据与对齐机制,它偏好生成结构完整、逻辑平滑的“安全文本”。要解决这一问题,核心不在于更换工具或复杂调参,而在于掌握提示词工程的底层逻辑:通过限制结构、注入细节、切换视角、打乱顺序等具体指令,引导模型生成更接近人类表达习惯的文本。本文基于实战经验,提供25个可

weixin_26824299的博客 258

为什么 ADT 在 SAP BTP ABAP environment 里认证成功却无法登录 Service Instance:根因拆解与一站式修复路线

摘要 ADT报错"认证成功但Service Instance登录失败"通常源于ABAP租户的权限或用户映射问题,而非账号密码错误。常见原因包括:1) ABAP租户内未创建对应业务用户;2) 业务用户缺少开发角色(如SAP_BR_DEVELOPER);3) BTP角色集合未分配或IdP组映射缺失;4) 浏览器会话混淆身份;5) 连接了非开发租户(如Customizing Tenant);6) 实例休眠导致误判。 解决方法:检查ABAP业务用户及角色分配,确认BTP角色集合映射,使用隐身窗口

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 252

poll、poll_wait函数与等待队列DECLARE_WAIT_QUEUE_HEAD、wake_up_interruptible()、wait_event_interruptible()使用

一、 poll()函数 应用层使用select()和poll()系统函数查询是否可对设备进行无阻塞的访问时,会引发设备驱动中的poll()函数被执行。

lihuan680680的博客 5755

GaussDB本地安装手册(主备模式)

如果实例状态是Normal,则安装成功。三节点集中式配置文件。

Sebastien23的博客 2631

linux进程阻塞非阻塞,Linux 内核机制--阻塞与非阻塞机制及Poll/Select分析

阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时,并不挂起。被挂起的进程进入sleep状态,被从调度器的运行队列移走,直到等待的条件被满足。在Linux驱动程序中,我们可以使用等待队列(wait queue)来实现阻塞操作。wait queue很早就作为一个基本的功能单位出现在Linux内核里了,它以队列为基础数据结构,...

weixin_36308612的博客 585

基于全局和局部接受性因果特征的广义学习模型,用于在线增量机械故障诊断

本文提出了一种**因果广义学习模型(CBLM)**,用于在线增量机械故障诊断。该模型结合了**全局因果特征**(时域、频域、故障特征频率均值)和**多尺度局部因果特征**(通过扩张卷积提取),构建了一个具有**增量学习能力**的广泛学习系统(BLS)。CBLM支持**结构增量学习**(增加增强节点)和**样本增量学习**(动态更新权重),无需重新训练整个模型,显著提高了计算效率和诊断精度。在两个滚动轴承数据集上的实验表明,CBLM在诊断准确性和训练时间上均优于传统深度学习模型,适用于在线实时故障诊断。

huanghm88的专栏 387

TPM 2.0实例探索2 —— LUKS磁盘加密(1)

本文对LUKS行了系统介绍

phmatthaus的专栏 1699

Linux 内核驱动--阻塞与非阻塞机制及Poll/Select分析if

阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时,并不挂起。被挂起的进程进入sleep状态,被从调度器的运行队列移走,直到等待的条件被满足。 在Linux驱动程序中,我们可以使用等待队列(wa

1486

Android 12.0 系统开机设置默认横屏显示

在12.0的系统产品开发中,对于产品需求来说,由于是宽屏设备所以产品需要开机默认横屏显示,开机横屏显示这就需要从两部分来实现,一部分是开机动画横屏显示,另一部分是系统显示横屏显示,从这两方面就可以做到开机默认横屏显示了。

安卓兼职framework和app工程师的博客 3743

Linux 内核驱动--阻塞与非阻塞机制及Poll/Select分析

阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时,并不挂起。被挂起的进程进入sleep状态,被从调度器的运行队列移走,直到等待的条件被满足。 在Linux驱动程序中,我们可以使用等待队列(wait queue)来实现阻塞操作。wait queue很早就作为一个基本的功能单位出现在Linux内核里了,它以队列为基础数

hardy_2009的专栏 852

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Linux select/poll机制原理分析

Blocking IO Model,阻塞IO模型;Nonblocking I/O Model,非阻塞IO模型;I/O Multiplexing Model,IO多路复用模型;Signal Driven I/O Model,信号驱动IO模型;Asynchronous I/O Model,异步IO模型;今天我们来分析下IO多路复用机制,在Linux中是通过机制来实现的。

smart_an的专栏 1101

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

eoll poll select总结

一、基础概念 1.I/O多路复用(multiplexing) 就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。 2.用户空间 / 内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。 操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有...

眞惜的博客 1324

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

深入剖析Netty源码设计(一)——深入理解select poll epoll机制

前言 打算输出一系列Netty源码分析与实践的文章,也作为后端开发学习过程中的沉淀,此文章为第一篇,从操作系统底层的IO讲起,为Netty 的出场做下知识准备。 一些概念 文件描述符 文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。读写文件也需要使用文件描述符来指定待...

舒哥的blog 4668

Linux select/poll/epoll

参考地址:https://www.jianshu.com/p/fe54ca4affe8

黑曼巴 8395

Linux——IO模式及 select、poll、epoll详解

一、概念说明 在进行解释之前,首先要说明几个概念: 用户空间和内核空间 进程切换 进程的阻塞 文件描述符 缓存 I/O 1.1、用户空间与内核空间 Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数据可能不在内存中。 Linux内核地址映射模型 x86 CPU采用了段页式地址映射模型。进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访

一口Linux的专栏 481

深入Linux内核理解epoll事件轮询机制

当某一进程调用 epoll_create 方法时,Linux 内核会创建一个 eventpoll 结构体,在内核cache 里建了个红黑树用于存储以后 epoll_ctl 传来的 socket 外,还会再建立一个 rdllist 双向链表,用于存储准备就绪的事件,当 epoll_wait 调用时,仅仅观察这个 rdllist 双向链表里有没有数据即可。有数据就返回,没有数据就 sleep,等到 timeout 时间到后即使链表没数据也返回。

不积跬步无以至千里 898

Linux内核-I/O多路复用[select]和I/O事件就绪通知源码分析

本文通过对select源码的探索,引出了socket创建,I/O事件就绪通知,时钟中断、tcp接收远端数据等机制的源码分析。

weixin_38597669的博客 1249

linux 内核IO模型&阻塞和非阻塞

【代码】linux 内核IO模型&阻塞和非阻塞。

本地服务器 747

Linux中的IO多路复用机制

原文地址:https://www.jianshu.com/p/397449cadc9a I/O多路复用(multiplexing)的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作 select、poll 和 epoll 都是 Linux API 提供的 IO 复用方式。 相信大家都...

gaoxueyi551的专栏 1569

深入理解 Linux I/O 多路复用:从 select 到 epoll演进之路

I/O 多路复用是一种使单个进程能够同时监控多个 I/O 通道(如网络连接、文件操作)状态的技术。它允许一个线程高效地管理多个网络连接,而无需为每个连接创建独立的线程或进程。在高并发服务器开发中,I/O 多路复用是突破性能瓶颈的关键技术,广泛应用于 Web 服务器、数据库系统、实时通信服务等需要处理海量并发连接的场景。技术演进时间线:1983年:select诞生于BSD 4.2,开创了I/O多路复用的先河1997年:poll出现,突破了文件描述符数量限制2002年。

2501_93078354的博客 740

【Linux】【进程】epoll内核实现总结+ET和LT模式内核实现方式

当某一进程调用方法时,Linux内核会创建一个结构体,这个结构体中有两个成员与epoll的使用方式密切相关.

m0_64014551的博客 1483

Linux内核中的IO模型详解

IO模型是Linux内核中处理输入输出的核心机制,它决定了应用程序如何与外设、文件、网络等进行数据交互。不同的IO模型有不同的特点和适用场景,理解这些模型对于开发高性能网络应用和系统级程序至关重要。本文将深入探讨Linux内核中的各种IO模型,包括阻塞IO、非阻塞IO、IO多路复用、信号驱动IO和异步IO等。

jiang_style的博客 2793
上一篇: Android程序的安全系统--以root权限进行操作
下一篇: 为什么在中断过程中不能进行睡眠
计算机与认知
博客等级 码龄14年 31粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值