[Android]进程间通信的方法
一、管道
管道是进程间通信中最古老的方式,它包括 无名管道 和 有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信。 无名管道由pipe()函数创建。
#include <stdio.h>
#include <unistd.h>
#define INPUT 0
#define OUTPUT 1
int main()
{
int files[2];
pid_t pid;
char buf[256];
int returned_count;
//创建无名管道
pipe(files);
//创建子进程
if((pid = fork()) == -1)
{
perror("fork() error");
return -1;
}
//执行子进程
if(pid == 0)
{
printf("in child process....\n");
//子进程向父进程写数据,关闭管道的读端
close(files[INPUT]);
write(files[OUTPUT],"test data", strlen("test data"));
exit(0);
}
else
{
//执行父进程
printf("in the parent process...\n");
//父进程从管道中读取子进程写的数据,关闭管道的写端
close(files[OUTPUT]);
returned_count = read(files[0], buf, sizeof(buf));
buf[returned_count] = '\0';
printf("%d bytes of data receiced from spawned process:%s\n", returned_count, buf);
}
return 0;
}
二、消息队列
消息队列用于运行于同一台机器上的进程间通信,它和管道很相似,是一个在系统内核中用来保存消息的队列,它在系统内核中是以消息链表的形式出现。消息链表中节点的结构用msg声明。
事实上,它是一种正逐步被淘汰的通信方式,我们可以用流管道或者套接口的方式来取代它。所以,我们对此方法也不再解释,也建议读者忽略这种方式。
三、共享内存
共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。得到共享内存有两种方式:映射/dev/mem设备和内存映像文件。前一种方式不给系统带来额外的开销,但在现实中并不常用,因为它控制存取的将是实际的物理内存,在Linux系统下,这只有通过限制Linux系统存取的内存才可以做到,这当然不太实际。常用的方式是通过shmXXX函数族来实现利 用共享内存进行存储的。 使用共享内存时要掌握的唯一诀窍是多个进程之间对一定存储区d同步访问。若服务器进程正在将数据放入共享内存,则在它做完这一操作之前,客户进程不应当去读取这些数据。 通常,信号量是用来实现对共享内存访问的同步(记录锁也可以用于这种场合)。 使用共享存储来实现进程间通信的注意点是对数据存取的同步,必须确保当一个进程去读取数据时,它所想要的数据已经写好了。通常,信号量被要来实现对共享存 储数据存取的同步,另外,可以通过使用shmctl函数设置共享存储内存的某些标志位如SHM_LOCK、SHM_UNLOCK等来实现。
四、信号
信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
五、信号量
信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是前一节的共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。一般说来,为了获得共享资源,进程需要执行下列操作:
(1) 测试控制该资源的信号量。
(2) 若此信号量的值为正,则允许进行使用该资源。进程将信号量减1。
(3)若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤(1)。
(4)当进程不再使用一个信号量控制的资源时,信号量值加1。如果此时有进程正在睡眠等待此信号量,则唤醒此进程。
维护信号量状态的是Linux内核操作系统而不是用户进程。我们可以从头文件/usr/src/linux/include/linux/sem.h 中看到内核用来维护信号量状态的各个结构的定义。信号量是一个数据集合,用户可以单独使用这一集合的每个元素。要调用的第一个函数是semget,用以获得一个信号量ID。
六、套接口
套接口(socket)编程是实现Linux系统和其他大多数操作系统中进程间通信的主要方式之一。我们熟悉的WWW服务、FTP服务等都是基于套接口编程来实现的。除了异地的计算机进程间外,套接口同样适用于本地同一台计算机内部的进程间通信。 关于这部分,可以参照《设计自己的网络蚂蚁》。那里由常用的几个套接口函数的介绍和示例程序。
这一部分或许是Linux进程间通信编程中最须关注和最吸引人的一部分,毕竟,Internet 正在我们身边以不可思议的速度发展着,如果一个程序员在设计编写他下一个程序的时候,根本没有考虑到网络,考虑到Internet,那么,可以说,他的设计很难成功。