linux中实现对输入的异步

1:传统的输入信号

传统的输入都是通过阻塞来实现,例如getchar一直等待用户输入。又或者是再curses库中的getch都是通过阻塞的方式来等待用户输入。那么想象一个场景要设计一个游戏,这个游戏可以让玩家动态输入一些值来动态调整游戏参数。不可能通过getchar这样的阻塞函数来获取用户输入把。那么这个该如何实现呢,再想象一下另外一种场景操作系统的CPU不可能是一直等待网卡的输入把。所以对于一些特别的场景阻塞输入是无法满足要求的。下面的这个例子就是一个阻塞输入的例子。

#include<stdio.h>
#include<stdlib.h>
#include<curses.h>

void init_setup (  );
void init_end (  );
void on_input (  );
void do_main (  );
int main ( int argc, char *argv[] )
{

        init_setup();
        on_input();
        do_main();
        init_end();
        return EXIT_SUCCESS;
}
        /* ----------  end of function main  ---------- */

void init_setup (  )
{
        initscr();
        crmode();
        noecho();
        clear();
}               /* -----  end of function init_setup  ----- */

void init_end (  )
{
        endwin();
}               /* -----  end of function init_end  ----- */

void on_input (  )
{
        char c;
        while((c = getch()) != ‘q‘){
                if(c == ‘w‘)
                mvaddch(20,20,‘!‘);
                else if(c == ‘e‘)
                mvaddch(20,20,‘0‘);
                else if(c == ‘r‘)
                mvaddch(20,20,‘t‘);
        }
}               /* -----  end of function on_input  ----- */

void do_main (  )
{
        while(1){
                move(50,50);
                addstr("do other thing");
        }

}               /* -----  end of function do_main  ----- */

从这个例子可以发现do_main没有执行,因为on_input一直等待用户输入阻塞了下面的程序运行。所以在有些场景像getchar或者getch这类的阻塞函数无法满足一些需求,那么就需要使用异步IO。异步IO的实现有两种方法:

1.设置输入O_ASYNC位

2.使用aio_read()

2:异步输入一

步骤如下:

1.设置0描述符,当输入就绪的时候发送信号

2.设置0描述符O_ASYNC标志位

2.设置信号处理函数。

下面是一个例子:

#include<stdio.h>
#include<stdlib.h>
#include<curses.h>
#include<signal.h>
#include<fcntl.h>
void init_setup (  );
void init_end (  );
void on_input (  );
void do_main (  );
void enable_kdb_signals();
int main ( int argc, char *argv[] )
{

        init_setup();
        enable_kdb_signals();
        signal(SIGIO,on_input);
        do_main();
        init_end();
        return EXIT_SUCCESS;
}
        /* ----------  end of function main  ---------- */

void init_setup (  )
{
        initscr();
        crmode();
        noecho();
        clear();
}               /* -----  end of function init_setup  ----- */

void init_end (  )
{
        endwin();
}               /* -----  end of function init_end  ----- */
void on_input (  )
{
        char c;
        c = getch();
        if(c == ‘w‘)
        mvaddch(20,20,‘!‘);
        else if(c == ‘e‘)
        mvaddch(20,20,‘0‘);
        else if(c == ‘r‘)
        mvaddch(20,20,‘t‘);
}               /* -----  end of function on_input  ----- */

void do_main (  )
{
        while(1){
                sleep(1);
                move(50,50);
                addstr("do other thing");
                refresh();
        }

}               /* -----  end of function do_main  ----- */

//设置输入时发送信号,设置输入为O_ASYNC
void enable_kdb_signals()
{
        int fd_flags;
        fcntl(0,F_SETOWN,getpid());
        fd_flags = fcntl(0,F_GETFL);
        fcntl(0,F_SETFL,(fd_flags|O_ASYNC));
}

上面这个例子可以看到do other thing以及输出,do_main正在运行,但是此时你输入字符程序可以通过信号处理函数on_input来接受输入进行响应。达到了异步的效果。

3:异步输入二

异步输入的第二种方法是通过aio_read来实现的,使用aio_read更加灵活,但是设置起来也比较复杂。

设置步骤如下:

1.设置信号处理函数,接受用户输入

2.设置aiocb结构体中的变量指明等待什么类型的输入,当输入的时候产生什么信号。

3.将aiocb结构体传递给aio_read来递交读入请求。

aiocb结构体定义如下:

         struct aiocb {
               /* The order of these fields is implementation-dependent */

               int             aio_fildes;     /* File descriptor */
               off_t           aio_offset;     /* File offset */
               volatile void  *aio_buf;        /* Location of buffer */
               size_t          aio_nbytes;     /* Length of transfer */
               int             aio_reqprio;    /* Request priority */
               struct sigevent aio_sigevent;   /* Notification method */
               int             aio_lio_opcode; /* Operation to be performed;
                                                  lio_listio() only */

               /* Various implementation-internal fields not shown */
           };
           
                  struct sigevent {
           int          sigev_notify; /* Notification method */
           int          sigev_signo;  /* Notification signal */
           union sigval sigev_value;  /* Data passed with
                                         notification */
           void       (*sigev_notify_function) (union sigval);
                            /* Function used for thread
                               notification (SIGEV_THREAD) */
           void        *sigev_notify_attributes;
                            /* Attributes for notification thread
                               (SIGEV_THREAD) */
           pid_t        sigev_notify_thread_id;
                            /* ID of thread to signal (SIGEV_THREAD_ID) */
       };

下面是一个简单的例子:

#include<stdio.h>
#include<stdlib.h>
#include<curses.h>
#include<signal.h>
#include<fcntl.h>
#include<aio.h>
void init_setup (  );
void init_end (  );
void on_input (  );
void do_main (  );
void setup_aio_buffer();
struct aiocb kbcbuf;
int main ( int argc, char *argv[] )
{

        init_setup();
        signal(SIGIO,on_input);
        setup_aio_buffer();
        aio_read(&kbcbuf);
        do_main();
        init_end();
        return EXIT_SUCCESS;
}
        /* ----------  end of function main  ---------- */

void init_setup (  )
{
        initscr();
        crmode();
        noecho();
        clear();
}               /* -----  end of function init_setup  ----- */

void init_end (  )
{
        endwin();
}               /* -----  end of function init_end  ----- */
void on_input (  )
{
        char c;
        char *cp = (char *)kbcbuf.aio_buf;
        if(aio_error(&kbcbuf) != 0)
                perror("reading faild");
        else
        if(aio_return(&kbcbuf) ==1){
                c = *cp;
                if(c == ‘w‘)
                mvaddch(20,20,‘!‘);
                else if(c == ‘e‘)
                mvaddch(20,20,‘0‘);
                else if(c == ‘r‘)
                mvaddch(20,20,‘t‘);
        }
        aio_read(&kbcbuf);
}               /* -----  end of function on_input  ----- */

void do_main (  )
{
        while(1){
                sleep(1);
                move(50,50);
                addstr("do other thing");
                refresh();
        }

}               /* -----  end of function do_main  ----- */

void setup_aio_buffer()
{
        static char input[1];
        kbcbuf.aio_fildes = 0;
        #设置接受输入的buf
        kbcbuf.aio_buf = input;
        #设置接受输入的字节大小
        kbcbuf.aio_nbytes = 1;
        kbcbuf.aio_offset = 0;
        #设置处理输入的方法
        #SIGE_SIGNAL 代表通过发送信号来处理
        kbcbuf.aio_sigevent.sigev_notify =SIGEV_SIGNAL;
        #设置要发送的信号
        kbcbuf.aio_sigevent.sigev_signo = SIGIO;
}

linux中实现对输入的异步

时间: 2024-12-16 10:08:53

linux中实现对输入的异步的相关文章

Linux中接收键盘输入

read 选项 变量名 -p    "提示信息" -t     指定等待时间,不指定则一直等待 -n    指定接收的字符数,不指定则不限制 -s    隐藏输入的数据,适用于机密信息的输入 [[email protected] sh]# vi param_test3.sh [[email protected] sh]# cat param_test3.sh #!/bin/bash # 提示用户输入并等待30秒,并将输入结果存入name变量中 read -t 30 -p "P

“品品Linux中的输入输出”

Linux中的输入输出 输入stdin[标准输入流]输入是指系统外接向系统传递的信息系统外接向系统中传递数据的方式如下1.键盘2.鼠标3.输入命令输出 输出 standout[标准正确输入] stderr[标准错误输出] 在命令顺利执行完成后的字符串 在命令失败执行完成后产生的字符串 在linux中的输出信号为1 stderr在linux中的输出信号为2 字符设备字符设备是指在I/O传输过程中以字符为单位进行传输的设备,例如键盘,打印机等字符设备是内存中开启的虚拟设备并真实存在 重定向输出fin

Linux中定时清除指定目录中30分钟前生成的特定文件

1,在/root/deltts目录下,创建脚本 vi clearBigtrc03.sh,输入以下脚本.保存并退出 #!/bin/sh find /root/uploadFiles -mmin +30 -name *.mp3 -exec rm {} \; 2,给文件赋予执行权限 chmod 755 clearBigtrc03.sh 3,添加Linux中的定时任务 输入crontab -e打开定时任务编辑,在最后增加一行如下,然后保存退出 表示每3分钟执行一次脚本 */3 * * * * /root

linux中的输入从定向和输出重定向

linux的标准的输入和输出为如下 我们在 linux中执行命令时,命令默认输出到console中,很多时候我们需要将命令输出到其他设备上如最常见的就文件中去,或者重文件中输入.那这时候就需要用到linux的输入和输出的重定向了. 常用文件重定向命令: command >file: 标准输出重定向到一个文件,错误仍然输出屏幕 command >>file: 标准输出重定向到一个文件(追加) command 1>file1: 标准输出重定向到一个文件 command 2>>

Linux 中的零拷贝技术,第 2 部分

技术实现 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.第一部分主要介绍了一些零拷贝技术的相关背景知识,简要概述了 Linux 为什么需要零拷贝技术以及 Linux 中都有哪几种零拷贝技术.本文是本系列文章的第二部分,针对第一部分内容中提到的几种零拷贝技术分别进行更详细的介绍,并对这些零拷贝技术的优缺点进行分析. 0 评论: 黄 晓晨, 软件工程师, IBM 冯 瑞, 软件工程师, IBM 2011 年 1

Linux中的磁盘

Linux的磁盘管理 (很重要请注意高能预警) 硬盘:几个盘片,双面,磁性颗粒, 处理速率不同步:借助于一个中间层 文件系统(FileSystem)     可以实现对磁盘行的文件进行读写     文件系统其实就是一个特殊软件,是直接安装到硬盘上的 硬盘分类     机械硬盘:         盘片组,磁头,磁头臂         马达.空气过滤片     固态硬盘         类似与内存的结构 机械硬盘简介     磁道(Track):磁盘旋转时候的同心圆,磁道编号从外向内,从0开始编号.

linux中常用时间和字符串之间相互转化

在Linux中经常会遇到时间和字符串相互转化的情形,有两个函数专门对应相应的转化. 1.时间转字符串函数strftime 函数原型:size_t strftime(char *s,size_t maxsize,char *format,conststruct tm *timeptr) strftime函数对timeptr指向的tm结构所代表的时间和日期进行格式编排,其结果放在字符串s中.该字符串的长度被设置为(最少)maxsize个字符.格式字符串format用来对写入字符串的字符进行控制,它包

centos linux中怎么查看和修改计算机名/etc/sysconfig/network

centos linux中怎么查看和修改计算机名 查看计算机名:在终端输入hostname 修改的话 hostname +计算机名(重启后失效)要永久修改的话要修改配置文件/etc/sysconfig/network修改hostname=你要改的名字

linux中vim编辑器各种常用命令及用法

linux中vim编辑器的常用命令以及用法(注意严格区分大小写以及中英文): vim编辑器有三种模式,分别是:编辑模式,输入模式以及末行模式. 模式转换: 编辑模式>>>输入模式: i:在光标所在字符前面,转为输入模式(即转完后在光标所在字符前输入):                      I:在光标所在行的行首,转为输入模式(即转完后在行首输入,不包括行首空                         白) a:在光标所在字符后,转为输入模式(即转完后在光标所在字符后面输入):