linux 函数异步,linux中实现对输入的异步

1:传统的输入信号

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

#include

#include

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

#include

#include

#include

#include

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

#include

#include

#include

#include

#include

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux环境下,Python可以使用异步编程模型和锁来实现对共享资源的异步加锁。以下是一种可能的实现方式: 1. 导入必要的模块: ```python import asyncio import threading ``` 2. 创建一个全局的锁对象: ```python lock = threading.Lock() ``` 3. 定义一个异步函数,用于调用外部程序并加锁保护: ```python async def run_external_program(): # 获取锁 lock.acquire() try: # 调用外部程序,进行必要的操作 await asyncio.sleep(1) # 模拟外部程序的执行时间 finally: # 释放锁 lock.release() ``` 4. 定义一个异步函数,用于调用多个线程并异步执行: ```python async def main(): # 创建一个事件循环对象 loop = asyncio.get_running_loop() # 创建多个线程,并在每个线程调用异步函数 tasks = [] for i in range(5): task = loop.run_in_executor(None, run_external_program) tasks.append(task) # 等待所有任务完成 await asyncio.gather(*tasks) ``` 5. 运行主函数: ```python if __name__ == "__main__": asyncio.run(main()) ``` 上述代码通过使用异步函数和锁,实现了对多个线程调用外部程序的异步加锁保护。每个线程在调用外部程序之前会获取锁,并在完成操作后释放锁,确保共享资源的安全访问。同时,多个线程可以并行执行,提高程序的性能和效率。 需要注意的是,在使用异步加锁时,要确保对共享资源的访问都经过了合适的加锁和释放锁的处理,以避免出现竞态条件和数据不一致的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值