由一道面课题来询问进度间的通讯

   
周末面试遭遇一个面试题,标题是:

内需一个后缀维.streaming的拍卖模型文件,里面定义了数码来自、过滤条件、数据输出等

答案:Windows下进度通讯

1   文件映射   文件映射(Memory-Mapped Files)能使进度把公文内容作为进度地址区间一块内存那样来对待。因而,进度不必采用文件I/O操作,只需不难的指针操作就可读取和修改文件的情节。
  Win32 API允许四个进程访问同一文件映射对象,各类进度在它和谐的地点空间里收受内存的指针。通过使用这个指针,不一致进度就足以读或涂改文件的内容,完成了对文本中多少的共享。
  应用程序有三种办法来使两个经过共享一个文书映射对象。
  (1)继承:第二个经过建立文件映射对象,它的子进度继承该目的的句柄。
  (2)命名文件映射:首个经过在确立文件映射对象时可以给该目标指定一个名字(可与公事名差别)。第一个经过可经过那几个名字打开此文件映射对象。此外,第二个进度也足以通过一些其余IPC机制(盛名管道、邮件槽等)把名字传给第一个经过。
  (3)句柄复制:首个经过建立文件映射对象,然后通过其余IPC机制(闻明管道、邮件槽等)把对象句柄传递给第二个经过。第三个经过复制该句柄就赢得对该公文映射对象的访问权限。
  文件映射是在七个经过间共享数据的百般实惠措施,有较好的安全性。但文件映射只好用于地点机械的经过之间,不可能用来网络中,而开发者还必须控制进程间的一起。
2  共享内存
  Win32 API中共享内存(Shared Memory)实际就是文本映射的一种新鲜景况。进程在创制文件映射对象时用0xFFFFFFFF来代表文件句柄(HANDLE),就象征了相应的文本映射对象是从操作系统页面文件访问内存,其他进度打开该公文映射对象就足以访问该内存块。由于共享内存是用文件映射落成的,所以它也有较好的安全性,也不得不运行于同一总结机上的经过之间。

  注意点:
要控制同步,而且CString、list、arry、map等的collect
class都不能安然的运用于共享内存中

     
不要把具备虚函数之C++类放到共享内存中

      不要把CObject派生类之MFC对象放置共享内存中

      不要选拔”point within the shared
memory”的指针

      不要选用”point outside of the
shared memory”的指针

     
使用”based”指针是平安的,但要小心使用
3  匿名管道

  管道(Pipe)是一种具有五个端点的通讯通道:有一端句柄的历程可以和有另一端句柄的长河通讯。管道可以是单向-一端是只读的,另一端点是只写的;也得以是双向的一管道的两端点既可读也可写。
  匿名管道(Anonymous Pipe)是 在父进程和子进度之间,或一致父进度的三个子进程之间传输数据的无名字的单向管道。寻常由父进度创建管道,然后由要通讯的子进度继承通道的读端点句柄或写 端点句柄,然后完结通讯。父进度还可以建立四个或更五个继续匿名管道读和写句柄的子进度。这么些子进度可以接纳管道直接通讯,不须求经过父进度。
  匿名管道是单机上完毕子进程标准I/O重定向的卓有成效措施,它不可以在网上使用,也不可能用于多个不相干的经过之间。
4  命名管道
  命名管道(Named Pipe)是服务器进度和一个或四个客户进度之间通讯的单向或双向管道。分化于匿名管道的是命名管道可以在不相干的进程之间和见仁见智电脑之间利用,服务器建立命名管道时给它指定一个名字,任何进度都足以通过该名字打开管道的另一头,根据给定的权能和服务器进度通信。
  命名管道提供了绝对简便易行的编程接口,使通过网络传输数据并不比同一计算机上两进程之间通讯更不方便,然而只要要同时和多个进度通讯它就不可能了。
5  邮件槽
  邮件槽(Mailslots)提 供进程间单向通讯能力,任何进度都能树立邮件槽成为邮件槽服务器。其它进度,称为邮件槽客户,可以通过邮件槽的名字给邮件槽服务器进度发送音信。进来的消 息一直位居邮件槽中,直到服务器进程读取它截止。一个进度既可以是邮件槽服务器也可以是邮件槽客户,由此可创设两个邮件槽落成进度间的双向通讯。
  通过邮件槽可以给地点电脑上的邮件槽、其余统计机上的邮件槽或指定互连网区域中所有电脑上有同样名字的邮件槽发送音信。广播通信的消息长度无法领先400字节,非广播音信的尺寸则受邮件槽服务器指定的最大消息长度的界定。
  邮件槽与命名管道相似,可是它传输数据是透过不可相信的数据报(如TCP/IP协议中的UDP包)完毕的,一旦互联网暴发错误则无从有限帮助音讯正确地接到,而命名管道传输数据则是赤手空拳在保证一连基础上的。不过邮件槽有简化的编程接口和给指定互联网区域内的有着电脑广播信息的能力,所以邮件槽不失为应用程序发送和选用新闻的另一种选拔。
6  剪贴板
  剪贴板(Clipped Board)实质是Win32 API中一组用来传输数据的函数和音讯,为Windows应用程序之间举行多少共享提供了一个中介,Windows已确立的撤并(复制)-粘贴的机制为不相同应用程序之间共享分化格式数据提供了一条走后门。当用户在应用程序中履行剪切或复制操作时,应用程序把挑选的多少用一种或各样格式放在剪贴板上。然后其它其余应用程序都可以从剪贴板上捡拾数据,从给定格式中挑选切合自己的格式。
  剪贴板是一个格外松懈的置换媒介,可以扶助其余数据格式,每一格式由一无符号整数标识,对规范(预订义)剪贴板格式,该值是Win32 API定义的常量;对非标准格式可以运用Register Clipboard Format函数注册为新的剪贴板格式。利用剪贴板举办交流的数码只需在数额格式上等同或都得以转账为某种格式就行。但剪贴板只能够在根据Windows的次序中使用,不能在网络上接纳
7 动态数据交流
  动态数据调换(DDE)是应用共享内设有应用程序之间展开数据交流的一种进度间通讯方式。应用程序可以行使DDE进行四遍性数据传输,也可以当出现新数据时,通过发送更新值在应用程序间动态调换数据。
  DDE和剪贴板一样既辅助标准数量格式(如文本、位图等),又可以协助自己定义的数目格式。但它们的数码传输体制却差别,一个眼看有别于是剪贴板操作大约总是用作对用户指定操作的五回性应答-如从菜单中选拔Paste命令。固然DDE也足以由用户启动,但它一而再发挥功效一般不要用户越发干涉。DDE有二种数据交流方式:
  (1) 冷链:数据沟通是三遍性数据传输,与剪贴板相同。
  (2) 温链:当数据互换时服务器公告客户,然后客户必须请求新的多寡。
  (3) 热链:当数据沟通时服务器自动给客户发送数据。
  DDE沟通可以发生在单机或网络中不一致电脑的应用程序之间。开发者还是可以定义定制的DDE数据格式进行应用程序之间尤其目标IPC,它们有更连贯耦合的通讯须要。大部分根据Windows的应用程序都援助DDE。
8 对象连接与嵌入
  应用程序利用对象连接与嵌入(OLE)技术管理复合文档(由七种数目格式组成的文档),OLE提供使某应用程序更便于调用其他应用程序举办多少编辑的劳务。例如,OLE扶助的字处理器可以嵌套电子表格,当用户要编制电子表格时OLE库可活动启动电子表格编辑器。当用户退出电子表格编辑器时,该表格已在原始字处理器文档中得到更新。在此处电子表格编辑器变成了字处理器的增添,而如果拔取DDE,用户要显式地开行电子表格编辑器。
  同DDE技术一样,半数以上依据Windows的应用程序都协助OLE技术。
9 动态连接库
  Win32动态连接库(DLL)中的全局数据可以被调用DLL的富有进程共享,这就又给进度间通讯开辟了一条新的不二法门,当然访问时要专注同步难点。
  纵然可以通过DLL进行进程间数据共享,但从数量安全的角度考虑,我们并不提倡那种办法,使用带有访问权限控制的共享内存的章程更好有的。
10 远程进度调用
  Win32 API提供的长途过程调用(RPC)使应用程序能够利用远程调用函数,那使在互连网上用RPC进行进度通讯就像是函数调用那样简单。RPC既可以在单机分化进程间选用也可以在网络中使用。
  由于Win32 API提供的RPC遵守OSF-DCE(Open Software Foundation Distributed Computing Environment)标准。所以经过Win32 API编写的RPC应用程序能与其余操作系统上支撑DEC的RPC应用程序通信。使用RPC开发者能够创制高品质、紧密耦合的分布式应用程序。
11 NetBios函数
  Win32 API提供NetBios函数用于拍卖低级互连网决定,那重假如为IBM NetBios系统编制与Windows的接口。除非那一个有异样低级网络功效需求的应用程序,别的应用程序最好不用拔取NetBios函数来进行进程间通讯。
12 Sockets
  Windows Sockets规范是以U.C.Berkeley高校BSD UNIX中盛行的Socket接口为范例定义的一套Windows下的网络编程接口。除了伯克利 Socket原有的库函数以外,还扩张了一组针对Windows的函数,使程序员可以充裕利用Windows的音信机制进行编程。
  现在透过Sockets完结进度通信的互连网使用越多,那关键的原由是Sockets的跨平台性要比任何IPC机制好得多,其余WinSock 2.0不仅辅助TCP/IP协议,而且还帮忙任何协议(如IPX)。Sockets的唯一缺点是它协理的是底层通讯操作,那使得在单机的进度间开展简易多少传递不太便宜,这时使用下边将介绍的WM_COPYDATA新闻将更合适些。
13 WM_COPYDATA消息
  WM_COPYDATA是一种相当有力却鲜为人知的消息。当一个采用向另一个用到传送数据时,发送方只需拔取调用SendMessage函数,参数是目标窗口的句柄、传递数据的前奏地址、WM_COPYDATA音讯。接收方只需像处理任何新闻这样处理WM_COPY DATA信息,那样收发双方就兑现了多少共享。
  WM_COPYDATA是一种万分简单的章程,它在底部实际上是通过文件映射来兑现的。它的弱项是看人下菜不高,并且它不得不用于Windows平台的单机环境下。 

 

图片 1

在MMO游戏中,服务器采取Linux操作系统,网络通信与游戏逻辑处理进程一般是分离的。
诸如:GameSvr进度处理游戏逻辑,TCPSvr进度处理互联网通信。Linux操作系统提供了累累体制可以兑现GameSvr和TCPSvr进度之间的数目通信。请您列出两种你觉得最好的编制来,并为主(最好)次(次佳)描述他们完结的框架,优缺点相比和应用中的注意事项。

组成Spark的streaming流处理框架,将种种数据开展批量拍卖、存储。

答案:Linux下进度通讯

一、进程间通讯概述
经过通讯有如下一些目标:
A、数据传输:一个经过须要将它的数据发送给另一个历程,发送的数据量在一个字节到几M字节之间
B、共享数据:八个经过想要操作共享数据,一个过程对共享数据的修改,其余进度应该立刻看出。
C、通告事件:一个进度需要向另一个或一组经过发送新闻,文告它(它们)暴发了某种事件(如进度终止时要通报父进度)。
D、资源共享:三个进程之间共享同样的资源。为了作到那或多或少,需求内核提供锁和共同机制。
E、进度控制:有些进程希望完全控制另一个进程的推行(如Debug进度),此时决定进度希望可以拦截另一个历程的持有陷入和那么些,并可以登时知晓它的事态改变。
Linux
进度间通讯(IPC)以下以几局地迈入而来:
先前时期UNIX进程间通讯、基于System
V进度间通讯、基于Socket进度间通讯和POSIX进程间通讯。
UNIX进度间通讯形式包含:管道、FIFO、信号。
System V进程间通讯格局包涵:System
V音信队列、System V信号灯、System V共享内存、
POSIX进度间通讯包含:posix新闻队列、posix信号灯、posix共享内存。
当今linux使用的进程间通讯格局:
(1)管道(pipe)和老牌管道(FIFO)
(2)信号(signal)
(3)音信队列
(4)共享内存
(5)信号量
(6)套接字(socket)

二、管道通讯

平时的Linux
shell都同意重定向,而重定向使用的就是管道。例如:
ps | grep vsftpd
.管道是单向的、先进先出的、无协会的、固定大小的字节流,它把一个进度的正经输出和另一个进度的正统输入连接在一道。写进程在管道的尾端写入数据,读进度在管道的道端读出多少。数据读出后将从管道中移走,其他读进度都无法再读到那么些数量。管道提供了简单的流控制机制。进程试图读空管道时,在有多少写入管道前,进度将间接不通。同样,管道已经满时,进度再试图写管道,在其余进度从管道中移走多少往日,写进度将平昔不通。管道紧要用于分裂进程间通讯。

管道创制与关闭
开创一个简约的管道,可以行使系统调用pipe()。它接受一个参数,也就是一个概括几个整数的数组。如若系统调用成功,此数组将包蕴管道使用的五个文本讲述符。成立一个管道之后,一般景色下进度将发出一个新的经过。
系统调用:pipe();
原型:int pipe(int fd[2]);
再次回到值:假使系统调用成功,重回0。假如系统调用败北再次来到-1:
errno=EMFILE(没有空亲的文件讲述符)
      EMFILE(系统文件表已满)
      EFAULT(fd数组无效)
注意:fd[0]用以读取管道,fd[1]用于写入管道。
图见附件
管道的创立
#include<unistd.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
int pipe_fd[2];
if(pipe(pipe_fd)<0){
printf(“pipe create error\n”);
return -1;
}
else
printf(“pipe create
success\n”);
close(pipe_fd[0]);
close(pipe_fd[1]);
}

管道的读写
管道首要用来分裂进度间通讯。实际上,平时先创造一个管道,再通过fork函数创制一个子历程。图见附件。

子进度写入和父进程读的命名管道:图见附件

管道读写注意事项:
可以透过打开五个管道来创立一个双向的管道。但需求在子理程中正确地安装文件讲述符。必须在系统调用fork()中调用pipe(),否则子进度将不会屡次三番文件讲述符。当使用半双工管道时,任何关系的历程都必须共享一个有关的先世进度。因为管道存在于系统基本之中,所以任何不在成立管道的进度的上代进度之中的经过都将无法寻址它。而在命名管道中却不是这么。管道实例见:pipe_rw.c

#include<unistd.h>
#include<memory.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
int pipe_fd[2];
pid_t pid;
char buf_r[100];
char* p_wbuf;
int r_num;

memset(buf_r,0,sizeof(buf_r));数组中的数据清0;

if(pipe(pipe_fd)<0){
printf(“pipe create error\n”);
return -1;
}

if((pid=fork())==0){
printf(“\n”);
close(pipe_fd[1]);
sleep(2);
if((r_num=read(pipe_fd[0],buf_r,100))>0){
printf(“%d numbers read from be pipe is
%s\n”,r_num,buf_r);
}
close(pipe_fd[0]);
exit(0);
}else if(pid>0){
close(pipe_fd[0]);
if(write(pipe_fd[1],”Hello”,5)!=-1)
printf(“parent write
success!\n”);
if(write(pipe_fd[1],”
Pipe”,5)!=-1)
printf(“parent wirte2
succes!\n”);
close(pipe_fd[1]);
sleep(3);
waitpid(pid,NULL,0);
exit(0);
}
}

正式流管道
与linux中文件操作有文件流的标准I/O一样,管道的操作也支撑基于文件流的情势。接口函数如下:
库函数:popen();
原型:FILE *open (char *command,char
*type);
返回值:若是成功,再次回到一个新的文本流。如若不能创造进度或者管道,重回NULL。管道中数据流的趋向是由第四个参数type控制的。此参数可以是r或者w,分别代表读或写。但不可能而且为读和写。在Linux
系统下,管道将会以参数type中第三个字符代表的不二法门打开。所以,假若你在参数type中写入rw,管道将会以读的方法打开。

动用popen()创设的管道必须采取pclose()关闭。其实,popen/pclose和标准文件输入/输出流中的fopen()/fclose()至极相似。
库函数:pclose();
原型:int pclose(FILE *stream);
再次回到值:重临系统调用wait4()的气象。
假诺stream无效,或者系统调用wait4()失利,则赶回-1。注意此库函数等待管道进度运行截至,然后倒闭文件流。库函数pclose()在应用popen()创建的长河上执行wait4()函数,它将损坏管道和文件系统。
流管道的事例。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#define BUFSIZE 1024
int main(){
FILE *fp;
char *cmd=”ps -ef”;
char buf[BUFSIZE];
buf[BUFSIZE]=’\0′;
if((fp=popen(cmd,”r”))==NULL)
 perror(“popen”);
while((fgets(buf,BUFSIZE,fp))!=NULL)
 printf(“%s”,buf);
pclose(fp);
exit(0);
}

取名管道(FIFO)
基本概念
取名管道和一般的管道基本相同,但也有部分明显的不一样:
A、命名管道是在文件系统中作为一个与众区其余设备文件而留存的。
B、分裂祖先的进程之间可以通过管道共享数据。
C、当共享管道的进度执行完所有的I/O操作之后,命名管道将继承保留在文件系统中以便将来选择。
管道只好由相关过程使用,它们一起的先世进程创设了管道。不过,通过FIFO,不相干的历程也能交流数据。

取名管道创设与操作
命名管道创立
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *pathname,mode_t
mode);
回到:若成功则为0,若出错重临-1
只要已经用mkfifo创立了一个FIFO,就可用open打开它。确实,一般的公文I/O函数(close,read,write,unlink等)都可用来FIFO。当打开一个FIFO时,非阻塞标(O_NONBLOCK)暴发下列影响:
(1)在相似景况中(没有表达O_NONBLOCK),只读打开要阻塞到某个其余进度为写打开此FIFO。类似,为写而开辟一个FIFO要阻塞到某个其余进度为读而打开它。
(2)如若指一了O_NONBLOCK,则只读打开登时赶回。可是,如若没有经过一度为读而打开一个FIFO,那么只写打开将出错再次回到,其errno是ENXIO。类似于管道,若写一个尚无进度为读而开辟的FIFO,则发出信号SIGPIPE。若某个FIFO的末段一个写进度关闭了该FIFO,则将为该FIFO的读进度爆发一个文书截至标志。
FIFO相关出错音信:
EACCES(无存取权限)
EEXIST(指定文件不设有)
ENAMETOOLONG(路径名太长)
ENOENT(包含的目录不设有)
ENOSPC(文件系统余空间不足)
ENOTDIR(文件路径无效)
EROFS(指定的文件存在于只读文件系统中)

fifo_write.c 
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FIFO “/tmp/myfifo”

main(int argc,char** argv)
{
char buf_r[100];
int fd;
int nread;
if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
printf(“cannot create
fifoserver\n”);
printf(“Preparing for reading
bytes….\n”);
memset(buf_r,0,sizeof(buf_r));
fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
if(fd==-1)
{
perror(“open”);
exit(1);
}
while(1){
memset(buf_r,0,sizeof(buf_r));
if((nread=read(fd,buf_r,100))==-1){
if(errno==EAGAIN)
printf(“no data yet\n”);
}
printf(“read %s from
FIFO\n”,buf_r);
sleep(1);
}
pause();
unlink(FIFO);
}

fifo_read.c
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FIFO_SERVER
“/tmp/myfifo”
main(int argc,char** argv)
{
int fd;
char w_buf[100];
int nwrite;
if(fd==-1)
if(errno==ENXIO)
printf(“open error;no reading
process\n”);
fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
if(argc==1)
printf(“Please send
something\n”);
strcpy(w_buf,argv[1]);
if((nwrite=write(fd,w_buf,100))==-1)
{
if(errno==EAGAIN)
printf(“The FIFO has not been read yet.
Please try later\n”);
}
else 
printf(“write %s to the
FIFO\n”,w_buf);
}

三、信号
信号概述
信号是软件中断。信号(signal)机制是Unix系统中极其古老的进度之间的能信体制。它用于在一个或五个经过之间传递异步信号。很多条件能够爆发一个信号。
A、当用户按某些终端键时,发生信号。在终点上按DELETE键日常发生中断信号(SIGINT)。那是终止一个已失去控制程序的章程。
B、硬件极度暴发信号:除数为0、无效的仓储访问等等。那么些标准一般由硬件检测到,并将其打招呼内核。然后内核为该规范爆发时正在运作的经过发生适当的信号。例如,对于实施一个不行存储访问的长河爆发一个SIGSEGV。
C、进度用kill(2)函数可将信号发送给另一个经过或进程组。自然,有些限制:接收信号进和发送信号进度的享有都必须一律,或发送信号进度的的持有者必须是极品用户。
D、用户可用Kill(ID
值)命令将信号发送给其余进度。此程序是Kill函数的界面。常用此命令终止一个失控的后台进度。
E、当检测到某种软件条件现已发出,并将其关照有关进度时也发生信号。那里并不是指硬件发生条件(如被0除),而是软件条件。例如SIGURG(在互连网连接上盛传非规定波特率的数码)、SIGPIPE(在管道的读过程已为止后一个进度写此管道),以及SIGALRM(进度所设置的闹钟时间已经晚点)。

基础为经过生产信号,来响应不相同的风浪,那几个事件就是信号源。首要信号源如下:
(1)十分:进程运行进度中出现很是;
(2)其余进度:一个进度可以向另一个或一组经过发送信号;
(3)终端中断:Ctrl-c,Ctro-\等;
(4)作业控制:前台、后台进度的保管;
(5)分配额:CPU超时或文件大小突破限制;
(6)公告:通告进程某事件发生,如I/O就绪等;
(7)报警:计时器到期;

Linux中的信号
1、SIGHUP 2、SIGINT(终止)
3、SIGQUIT(退出) 4、SIGILL 5、SIGTRAP 6、SIGIOT  7、SIGBUS  
8、SIGFPE   9、SIGKILL 10、SIGUSER 11、 SIGSEGV SIGUSER 12、 SIGPIPE
13、SIGALRM 14、SIGTERM 15、SIGCHLD 16、SIGCONT 17、SIGSTOP 18、SIGTSTP
19、SIGTTIN 20、SIGTTOU 21、SIGURG 22、SIGXCPU 23、SIGXFSZ 24、SIGVTALRM
25、SIGPROF 26、SIGWINCH 27、SIGIO 28、SIGPWR

常用的信号:
SIGHUP:从极限上暴发的完工信号;
SIGINT:来自键盘的中断信号(Ctrl+c)
SIGQUIT:来自键盘的淡出信号;
SIGFPE:浮点万分信号(例如浮点运算溢出);
SIGKILL:该信号为止接收信号的进度;
SIGALRM:进度的定时器到期时,发送该信号;
SIGTERM:kill命令生出的信号;
SIGCHLD:标识子进度截止或停止的信号;
SIGSTOP:来自键盘(Ctrl-Z)或调试程序的为止扫行信号

可以须要系统在某个信号出现时遵守下列二种形式中的一种举办操作。
(1)忽略此信号。超过半数信号都可使用那种方法开展拍卖,但有二种信号却未能被忽略。它们是:SIGKILL和SIGSTOP。那三种信号无法被忽视的,原因是:它们向顶级用户提供一种使进度终止或甘休的笃定办法。其它,借使疏忽某些由硬件相当暴发的信号(例如不合法储存访问或除以0),则经过的一颦一笑是示定义的。
(2)捕捉信号。为了做到那一点要通报内核在某种信号暴发时,调用一个用户函数。在用户函数中,可实施用户期待对那种事件开展的拍卖。假若捕捉到SIGCHLD信号,则表示子进度已经甘休,所以此信号的捕捉函数可以调用waitpid以得到该子进度的历程ID以及它的停下情状。
(3)执行系统默许动作。对多数信号的种类默认动作是终止该进度。每一个信号都有一个缺省动作,它是当进度没有给那么些信号指定处理程序时,内核查信号的拍卖。有5种缺省的动作:
(1)十分终止(abort):在经过的当前目录下,把进程的地址空间内容、寄存器内容保留到一个称为core的公文中,而后终止进度。
(2)退出(exit):不爆发core文件,间接终止进程。
(3)忽略(ignore):忽略该信号。
(4)甘休(stop):挂起该进程。
(5)继续(contiune):即使经过被挂起,刚復苏进度的动行。否则,忽略信号。

信号的出殡与捕捉
kill()和raise()
kill()不仅可以中止进程,也可以向进度发送其他信号。
与kill函数不一样的是,raise()函数运行向经过本身发送信号
#include<sys/types.h>
#include<signal.h>
int kill(pid_t pid,int signo);
int raise(int signo);
七个函数重返:若成功则为0,若出错则为-1。
kill的pid参数有七种差别的图景:
(1)pid>0将信号发送给进程ID为pid的经过。
(2)pid==0将信号发送给其进程组ID等于发送进程的进程组ID,而且发送进程有许可权向其发送信号的拥有进度。
(3)pid<0将信号发送给其进度组ID等于pid绝对值,而且发送进度有许可权向其发送信号的富有进度。如上所述一样,“所有进度”并不包蕴系统经过集中的长河。
(4)pid==-1 POSIX.1未定义种处境
kill.c 
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
pid_t pid;
int ret;
if((pid==fork())<0){
perro(“fork”);
exit(1);
}
if(pid==0){
raise(SIGSTOP);
exit(0);
}else {
printf(“pid=%d\n”,pid);
if((waitpid(pid,NULL,WNOHANG))==0){
if((ret=kill(pid,SIGKILL))==0)
printf(“kill %d\n”,pid);
else{
perror(“kill”);
}
}
}
}

alarm和pause函数
利用alarm函数可以安装一个时间值(闹钟时间),在未来的某个时刻时间值会被超过。当所设置的时间被当先后,爆发SIGALRM信号。若是不忽视或不捕捉引信号,则其默认动作是终止该进程。
#include<unistd.h>
unsigned int alarm(unsigned int
secondss);
回到:0或以前设置的闹钟时间的余留秒数。

参数seconds的值是秒数,经过了指定的seconds秒后暴发信号SIGALRM。每个进度只好有一个闹钟时间。要是在调用alarm时,从前已为该进度设置过闹钟时间,而且它还平昔不过期,则该闹钟时间的余留值作为这一次alarm函数调用的值重临。之前注册的闹钟时间则被新值代换。
倘使有以前注册的尚未当先的闹钟时间,而且seconds值是0,则废除往日的闹钟时间,其余留值仍作为函数的再次来到值。

pause函数使用调用进度挂起直到捕捉到一个信号
#include<unistd.h>
int pause(void);
返回:-1,errno设置为EINTR
只有履行了一信号处理程序并从其回来时,pause才回到。

alarm.c
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int ret;
ret=alarm(5);
pause();
printf(“I have been waken
up.\n”,ret);
}

信号的拍卖
当系统捕捉到某个信号时,可以忽略什么人信号也许使用指定的处理函数来处理该信号,或者使用系统默许的艺术。信号处理的第一格局有三种,一种是行使简单的signal函数,别一种是采纳信号集函数组。
signal()
#include<signal.h>
void (*signal (int signo,void
(*func)(int)))(int)
归来:成功则为从前的信号处理配置,若出错则为SIG_ERR
func的值是:(a)常数SIGIGN,或(b)常数SIGDFL,或(c)当收到此信号后要调用的的函数的地方。若是指定SIGIGN,则向基础表示忽略此信号(有四个信号SIGKILL和SIGSTOP不可能忽视)。若是指定SIGDFL,则意味着接到此信号后的动作是系统默许动作。当指定函数地址时,大家称此为捕捉此信号。大家称此函数为信号处理程序(signal
handler)或信号捕捉函数(signal-catching
funcgion).signal函数原型太复杂了,假诺运用上边的typedef,则可以使其简化。
type void sign(int);
sign *signal(int,handler *);
实例见:mysignal.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
void my_func(int sign_no)
{
if(sign_no==SIGINT)
 printf(“I have get SIGINT\n”);
else if(sign_no==SIGQUIT)
 printf(“I have get
SIGQUIT\n”);
}
int main()
{
 printf(“Waiting for signal SIGINT or
SIGQUTI\n”);
 signal(SIGINT,my_func);
 signal(SIGQUIT,my_func);
 pasue();
 exit(0);
}
信号集函数组
大家须要有一个能表示多少个信号——信号集(signal
set)的数据类型。将在sigprocmask()那样的函数中选取那种数据类型,以告知内核不一致意暴发该信号集中的信号。信号集函数组包蕴水量几大模块:成立函数集、登记信号集、检测信号集。
图见附件。

创制函数集
#include<signal.h>
int sigemptyset(sigset_t*
set);
int sigfillset(sigset_t* set);
int sigaddset(sigset_t* set,int signo
);
int sigdelset(sigset_t* set,int
signo);
七个函数重临:若成功则为0,若出错则为-1
int sigismember(const sigset_t* set,int
signo);
归来:若真则为1,若假则为0;
signemptyset:开端化信号集合为空。
sigfillset:开端化信号集合为保有的信号集合。
sigaddset:将指定信号添加到现存集中。
sigdelset:从信号集中删除指定信号。
sigismember:查询指定信号是不是在信号集中。

登记信号集
登记信号处理机首要用来决定进度怎么样处理信号。首先要看清出脚下经过阻塞能仍然不能够传递给该信号的信号集。那第一使用sigprocmask函数判断检测或更改信号屏蔽字,然后采纳sigaction函数改变进程接受到一定信号将来的行为。
一个经过的信号屏蔽字可以规定当前不通而不可以递送给该进度的信号集。调用函数sigprocmask可以检测或改变(或双方)进度的信号屏蔽字。
#include<signal.h>
int sigprocmask(int how,const sigset_t*
set,sigset_t* oset);
回来:若成功则为0,若出错则为-1
oset是非空指针,进度是近日信号屏蔽字通过oset再次来到。其次,若set是一个非空指针,则参数how提示如何修改当前信号屏蔽字。
用sigprocmask更改当前信号屏蔽字的章程。how参数设定:
SIG_BLOCK该进程新的信号屏蔽字是其眼前信号屏蔽字和set指向信号集的并集。set包罗了俺们意在阻塞的增大信号。
SIG_NUBLOCK该进度新的信号屏蔽字是其眼前信号屏蔽字和set所指向信号集的混合。set蕴涵了大家愿意消除阻塞的信号。
SIG_SETMASK该进程新的信号屏蔽是set指向的值。就算set是个空指针,则不更改该进度的信号屏蔽字,how的值也无意义。
sigaction函数的出力是检查或涂改(或二者)与指定信号相关联的处理动作。此函数取代了UNIX早期版本接纳的signal函数。
#include<signal.h>
int sigaction(int signo,const struct
sigaction* act,struct sigaction* oact);
重返:若成功则为0,若出错则为-1
参数signo是要检测或涂改具体动作的信号的编号数。若act指针非空,则要修改其动作。若是oact指针为空,则系统重回该信号的本来动作。此函数使用下列结构:
struct sigaction{
void (*sa_handler)(int signo);
sigset_t sa_mask;
int sa_flags;
void (*sa_restore);
};
sa_handler是一个函数指针,指定信号关联函数,能够是自定义处理函数,还是能SIG_DEF或SIG_IGN;
sa_mask是一个信号集,它可以指定在信号处理程序执行进度中如何信号应当被堵塞。
sa_flags中富含众多标志位,是对信号进行处理的种种选项。具体如下:
SA_NODEFER\SA_NOMASK:当捕捉到此信号时,在实践其信号捕捉函数时,系统不会自动阻塞此信号。
SA_NOCLDSTOP:进度忽略子进度发生的其他SIGSTOP、SIGTSTP、SIGTTIN和SIGTOU信号
SA_RESTART:可让重启的种类调用重新起成效。
SA_ONESHOT\SA_RESETHAND:自定义信号只进行一回,在执行完成后卷土重来信号的连串默许动作。
检测信号是信号处理的接二连三手续,但不是必须的。sigpending函数运行进度检测“未决“信号(进度不知底她的存在),并一发操纵对她们做何处理。
sigpending再次来到对于调用进度被堵塞无法递送和近年来未决的信号集。
#include<signal.h>
int sigpending(sigset_t *
set);
回来:若成功则为0,若出错则为-1
信号集实例见:sigaction.c
#include<sys/types.h>
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
void my_func(int signum){
printf(“If you want to quit,please try
SIGQUIT\n”);
}
int main()
{
sigset_t set,pendset;
struct sigaction
action1,action2;
if(sigemptyse(&set)<0)
perror(“sigemptyset”);
if(sigaddset(&set,SIGQUIT)<0)
perror(“sigaddset”);
if(sigaddset(&set,SIGINT)<0)
perror(“sigaddset”);
if(sigprocmask(SIG_BLOCK,&set,NULL)<0)
perror(“sigprcmask”);
esle{
printf(“blocked\n”);
sleep(5);
}
if(sigprocmask(SIG_UNBLOCK,&set,NULL)
perror(“sigprocmask”);
else
printf(“unblock\n”);
while(1){
if(sigismember(&set,SIGINT)){
sigemptyset(&action1.sa_mask);
action1.sa_handler=my_func;
sigaction(SIGINT,&action1,NULL);
}else
if(sigismember(&set,SIGQUIT)){
sigemptyset(&action2.sa_mask);
action2.sa_handler=SIG_DEL;
sigaction(SIGTERM,&action2,NULL);
}
}
}

2)iServer 9D 的实时数据服务也提供了一晃三种处理办法

1、技术框架

3)进入主节点iServer的管制界面,点击发表实时数据服务,数据来自选用流处理模型,勾选数据流服务(即对外出口的劳务地点)

图片 2

图片 3

 前端运行效果如下:

图片 4

     集群布置,搭建iServer
集群服务后,在主节点发布实时数据服务,将数据流服务推送到各子节点即可

分化种类的实时数据,通过iServer筛选发布为数据流服务,客户端可一贯在前者调用。也足以由此ES等读取iServer的大数量目录服务,公布成对应服务一向调用

2)访问http://localhost:8080,检查spark环境是否启动正常

在iServer的 &iServer_home\iClient\forJavaScript\examples\leaflet,
编辑dataFlowService.html

总结:

iServer9D的实时数据服务可以经过各类通信协议对来源网络、物联网等实时流式数据举行采访、存储和剖析,iclient9d可以对实时数据服务进行订阅,iServer会通过WebSocket协商将采集的多寡实时推送至订阅的客户端并开展可视化展现。

图片 5

SuperMap
在十一月份公告了咬合大数目技术的9D新产品,明天就和我们介绍下iServer9D中的实时数据服务。

     单机安排,iServer 9D内置spark框架
,启动后,发表对应的实时数据服务和数据流服务即可。同时具有了实时数据服务器、数据流服务器、GIS服务器八个角色

5)使用iclient 前端加载实时数据

 图片 6

4)发表实时数据服务

          图片 7

4)数据流服务揭橥成功后,将在SuperMap iServer
服务列表页面中展现出来,单击{servicename}/dataflow 即可访问数据流服务
REST 页面,可以见见广播数据(broadcast)和订阅数据(subscribe)的接口,
订阅即可吸收到正在举办流处理的数码

1)启动iServer9D后,开启spark服务。添加到地头集群(相当于启动了spark的一个work节点)

2、处理的流程

3、应用范例

1)输入的多寡和输出的多寡

   图片 8

 图片 9

图片 10     
  图片 11

  • 质量过滤: 对输入的实时数据开展品质筛选,只突显符合条件的多寡      
  • 空中过滤:对输入的数码举行地理空间上的过滤,如只体现某一区域限量的多少
  • 质量映射:对输入的数额开展空间上的职位进行判断(和前三回的地方展开自查自纠),如下图的电子围栏判断 

3)安插实时数据服务

图片 12

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注