(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
创建: msgget();写入消息:msgsnd();读取消息:msgrcv();删除:msgctl();
(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
创建:shmget();附加:shmat();分离:shmdt();
(6)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
(7)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
创建:semget();控制删除:semctl();
(8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
一、管道
(1)管道
管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。读写管道的例程:
#include
#include
#include
#include
#include
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));
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 the 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 write1 success!\n");
if(write(pipe_fd[1]," Pipe",5)!=-1)
printf("parent write2 success!\n");
close(pipe_fd[1]);
sleep(3);
waitpid(pid,NULL,0); //等待子进程结束
exit(0);
}
}
(2)标准流管道
#include
#include
#include
#include
#define BUFSIZE 1000
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);
}
(3)命名管道
也叫FIFO,与管道不同,FIFO不是临时的对象,它们是文件系统中真正的实体,可以用mkfifo命令创建。只要有合适的访问权限,进程就可以使用FIFO。FIFO的打开方式和管道稍微不同。一个管道(它的两个file数据结构、VFS I节点和共享数据页)是一次性创建的,而FIFO已经存在,可以由它的用户打开和关闭。Linux必须处理在写进程打开FIFO之前读进程对它的打开,也必须处理在写进程写数据之前读进程对管道的读。除此以外,FIFO几乎和管道的处理完全一样,而且它们使用一样的数据结构和操作。
读进程:
#include
#include
#include
#include
#include
#include
#include
#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);
}
写进程:
#include
#include
#include
#include
#include
#include
#include
#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);
}
二、信号
(1)信号的发出:kill(),raise()给自身进程发送信号。
#include
#include
#include
#include
#include
int main()
{
pid_t pid;
int ret;
if((pid=fork())<0){
perror("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");
}
}
}
}
(2)alarm(),pause()
#include
#include
#include
int main()
{
int ret;
ret=alarm(5);
pause();
printf("I have been waken up.\n",ret);
}
(3)signal(),发送信号
ctrl+c:SIGINT,ctrl+/:SIGQUIT
#include
#include
#include
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 SIGQUIT \n ");
signal(SIGINT, my_func);
signal(SIGQUIT, my_func);
pause();
exit(0);
}
(4)信号集,接受多个信号,同时多个信号处理函数
#include
#include
#include
#include
#include
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(sigemptyset(&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("sigprocmask");
else
{
printf("blocked\n");
sleep(5);
}
if(sigprocmask(SIG_UNBLOCK,&set,NULL)<0)
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_DFL;
sigaction(SIGTERM,&action2,NULL);
}
}
}
相关推荐
关于4种实现IPC机制的例子
Linux系统中IPC机制的分析与实现.pdf
用java设计了一种安全高效的Java操作系统IPC机制
一种安全高效的Java操作系统IPC机制的设计与实现
**写作原因:跨进程通信的实现和理解是Android进阶中重要的一环。下面博主分享IPC一些相关知识、操作及自己在学习IPC过程中的一些理解。 这一章是为下面的Messenger和AIDL的使用做准备,主要讲解Android Service的...
<支持管道和=>?@ABCDEF等多种进程间通信机制.现有的进程间通信机制存在着访问控制 上的缺陷.可能会让攻击者获得部分或全部的系统控制权G分析了现有89:;<几种进程间通信的访问控制机 制.并提出了通过实现进程间通信的...
实验5 Linux 高级程序设计 1、实验目的 (1)了解Linux操作系统下应用程序开发流程 (2)掌握gun工具链的使用 (3)了解Linux高级编程技巧(例如IPC机制、系统调用等) 2、实验内容 1. 编写一个简单的C语言程序,编写...
android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信, 取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。 Binder通信是通过linux的binder driver来实现的。...
在linux下实现ipc问题的解决办法和代码
主要介绍了Android IPC机制中 Messager 实现跨进程通信的知识,对Android学习通信知识非常重要,需要的同学可以参考下
SIP协议的实现由osip和eXosip做为基础,SIP协议的介绍以及库的工作机制可以看提供的相关参考文档。 1.4 XML文本协议准备 XML文本协议主要是用作SIP的消息体,用以表述相关的操作实体内容,由libxml2的库来做底层,...
IPC 一个简单的C linux IPC程序,非常努力地尝试通过GPU /软件实现模拟队列和传入(永无止境)摄像机数据的处理。 :D
这是一个在Linux下的多进程程序,网上没有哦!
这四个角色的关系和互联网类似:Server是服务器,Client是客户终端,SMgr是域名服务器(DNS),驱动是路由器。 book.java package com.example.android_binder_testservice; import android.os.Parcel; import andr
一个简单的demo,通过AIDL的方式实现了IPC(进程间通信)。涉及AIDL中的客户端、服务端、观察者模式、重连机制、权限验证。
Android IPC机制Messenger实例详解 前言: Messenger可以翻译成信使,通过它可以在不同进程间传递Message对象有了它就可以轻松实现进程间的数据传递了。 Messenger使用的方法相对AIDL比较简单,它对AIDL做了一层封装...
主要介绍了Android使用Service实现IPC通信的2种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧