Linux异步命令 linux异步编程
linux系统c语言进程不想被sleep阻塞等待怎么解决?
1、启动后台子任务,在执行命令后加操作符,表示将命令放在子shell中异步执行。可以达到多线程效果。如下,sleep10#等待10秒,再继续下一操作sleep10当前shell不等待,后台子shell等待。
在应县等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站设计、成都网站建设 网站设计制作按需网站策划,公司网站建设,企业网站建设,品牌网站建设,全网营销推广,外贸网站制作,应县网站建设费用合理。
2、wait命令wait是用来阻塞当前进程的执行,直至指定的子进程执行结束后,才继续执行。使用wait可以在bash脚本“多进程”执行模式下,起到一些特殊控制的作用。
如何查看linux是否开启异步IO
查看linux是否开启异步IO命令如下:
[DATA@localhost ~]$ cat /proc/slabinfo | grep kio
kioctx 37 140 384 10 1 : tunables 54 27 8 : slabdata 14 14 0
kiocb 0 0 256 15 1 : tunables 120 60 8 : slabdata 0 0 0
返回结果中kiocp对应的前两项为0,说明系统中没有使用异步io。
linux异步通知之驱动层怎么释放SIGUSR1/SIGUSR2
首先,Linux中的信号可以通过kill -l命令获取,
如上图所示,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的),编号为32 ~ 63的信号是后来扩充的,称做可靠信号(实时信号)。不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会。
其次,SIGUSR1 ,这是留给用户使用的信号。一般在编程中使用。举例说明:sigqueue向本进程发送数据的信号,C语言代码如下 :
#include stdio.h
#include string.h
#include stdlib.h
#include signal.h
#include unistd.h
void myhandler(int signo,siginfo_t *si,void *ucontext);
int main(){
union sigval val;//定义一个携带数据的共用体
struct sigaction oldact,act;
act.sa_sigaction=myhandler;
act.sa_flags=SA_SIGINFO;//表示使用sa_sigaction指示的函数,处理完恢复默认,不阻塞处理过程中到达下在被处理的信号
//注册信号处理函数
sigaction(SIGUSR1,act,oldact);
char data[100];
int num=0;
while(num10){
sleep(2);
printf("等待SIGUSR1信号的到来\n");
sprintf(data,"%d",num++);
val.sival_ptr=data;
sigqueue(getpid(),SIGUSR1,val);//向本进程发送一个信号
}
}
void myhandler(int signo,siginfo_t *si,void *ucontext){
printf("已经收到SIGUSR1信号\n");
printf("%s\n",(char*)(si-si_ptr));
}
如何在Linux中使用flock控制程序的异步执行
# ... 后面的工作
这样虽然可以确保工作同时进行完毕,但是就是很慢…
另一种可能的方法是:
# 前面的工作
update_pkg_on_machine_1
update_pkg_on_machine_2
update_pkg_on_machine_3
sleep 10
# ... 后面的工作
这样子虽然可以同时进行工作,但是如果10秒内工作还没完成,接下来的工作可能就会出错了。
而工作要在多少秒之内做完,其实是很难掌握的。
利用 flock 来管理工作状态
我过去在自修作业系统的时候,有学到mutex这个东西,而 flock 就是可以在shell上使用的mutex。
linux中block IO,no-block IO,异步IO,IO多路复用笔记
现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。 为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操心系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间 。针对linux操作系统而言, 将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF) ,供内核使用,称为内核空间, 而将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF),供各个进程使用,称为用户空间。
文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述 指向文件的引用的抽象化概念 。文件描述符在形式上是一个非负整数。 实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表 。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
刚才说了,对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,它会经历两个阶段:
1、等待数据准备 (Waiting for the data to be ready)
2、将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
正式因为这两个阶段,linux系统产生了下面 五种网络模式 的方案。
阻塞 I/O(blocking IO)
非阻塞 I/O(nonblocking IO)
I/O 多路复用( IO multiplexing)
异步 I/O(asynchronous IO)
信号驱动 I/O( signal driven IO)
注:由于signal driven IO在实际中并不常用,所以我这只提及剩下的四种IO Model。
阻塞 I/O(blocking IO)
在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样:
当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据(对于网络IO来说,很多时候数据在一开始还没有到达。比如,还没有收到一个完整的UDP包。这个时候kernel就要等待足够的数据到来)。这个过程需要等待,也就是说数据被拷贝到操作系统内核的缓冲区中是需要一个过程的。而在用户进程这边,整个进程会被阻塞(当然,是进程自己选择的阻塞)。当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。
所以,blocking IO的特点就是在IO执行的两个阶段都被block了(内核阻塞读取数据,内核将数据复制到应用户态)。
非阻塞 I/O(nonblocking IO)
linux下,可以通过设置socket使其变为non-blocking。当对一个non-blocking socket执行读操作时,流程是这个样子:
当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。
所以,nonblocking IO的特点是用户进程需要 不断的主动询问 kernel数据好了没有( 内核读取数据时,用户态不需要阻塞,内核将数据复制到用户态时,需要阻塞 )。
I/O 多路复用( IO multiplexing)
IO multiplexing就是我们说的select,poll,epoll,有些地方也称这种IO方式为event driven IO。select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是 select,poll,epoll这个function会不断的轮询所负责的所有socket ,当某个socket有数据到达了,就通知用户进程。
当用户 进程调用了select , 那么整个进程会被block ,而同时,kernel会“监视”所有 select负责的socket(一个管理多个socket连接),当任何一个socket中的数据准备好了,select就会返回 。这个时候用户进程再调用read操作, 将数据从kernel拷贝到用户进程 。
所以,I/O 多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态,select()函数就可以返回。
这个图和blocking IO的图其实并没有太大的不同,事实上,还更差一些。 因为这里需要使用两个system call (select 和 recvfrom),而blocking IO只调用了一个system call (recvfrom) 。但是,用select的优势在于它可以同时处理多个connection。
所以,如果处理的 连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大 。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)
在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。
总结:IO多路复用其实也是阻塞的,阻塞的地方在用当有socket连接有数据以后, 会阻塞知道数据从内核复制到用户态(第二步阻塞)。
异步 I/O(asynchronous IO)
inux下的asynchronous IO其实用得很少。先看一下它的流程:
用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。
总结:两个阶段都不需要用户进程干涉,内核将数据准备好以后通知用户态去读取
总结
blocking和non-blocking的区别
调用blocking IO会一直block住对应的进程直到操作完成,而non-blocking IO在kernel还准备数据的情况下会立刻返回。
synchronous IO和asynchronous IO的区别
在说明synchronous IO和asynchronous IO的区别之前,需要先给出两者的定义。POSIX的定义是这样子的:
- A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
- An asynchronous I/O operation does not cause the requesting process to be blocked;
两者的区别就在于synchronous IO做”IO operation”的时候会将process阻塞。按照这个定义,之前所述的 blocking IO,non-blocking IO,IO multiplexing都属于synchronous IO 。
有人会说,non-blocking IO并没有被block啊。这里有个非常“狡猾”的地方,定义中所指的”IO operation”是指真实的IO操作,就是例子中的recvfrom这个system call。non-blocking IO在执行recvfrom这个system call的时候,如果kernel的数据没有准备好,这时候不会block进程。但是, 当kernel中数据准备好的时候,recvfrom会将数据从kernel拷贝到用户内存中,这个时候进程是被block了,在这段时间内,进程是被block的。
而asynchronous IO则不一样,当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。
文章题目:Linux异步命令 linux异步编程
当前网址:http://myzitong.com/article/hhjdoi.html