进程间通信

来源:互联网 发布:js input 当前日期 编辑:程序博客网 时间:2024/05/18 01:05

一、   为什么进程间需要通信

1 数据间传输  

   一个进程需要将它的数据发送给另一个进程。

2资源共享

多个进程共享同样的资源  进行协调

3 通知时间

一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件。

4 进程控制

有些进程希望完全控制另一个进程的执行,此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变。

常用的进程间通信方式

1管道(PIPE)和有名管道(fifo)            2信号(signal)         3消息队列          4共享内存           5信号量            6套接字


1  管道通信

  1)管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起。一个进程在管道(写进程)的尾部写入数据,另一个进程(读进程)从管道的头部读出数据。

2)管道创建

管道包括无名管道和有名管道两种,前者用于父进程和子进程间的通信。后者可用于运行与同一系统中的任意两个进程间的通信。无名管道创建用函数int pipe(int pipedis[2]).当不需要管道时,进行关闭。

不同进程间需要fork()一个子进程。子进程进行读管道,父进程进行写入管道。必须在系统调用fork()前调用pipe(),否则子进程将不会继承文件描述符。

命名管道和无名管道基本相同,但也有不同点:无名管道只能由父子进程使用;但是通过命名管道,不相关的进程也能交换数据。

#include<sys/types.h>

#include<sys/stat.h>

int mkfifo(const char* pathname,mode_t mode)

pathname:FIFO文件名

mode:属性   一旦创建了一个FIFO,就可以用open打开它,一般的文件访问函数(close\read\write等)都可用于FIFO。

2信号通信

1)信号机制是Unix系统中最为古老的进程间通信机制,很多条件可以产生一个信号:

当用户按某些按键时,产生信号;

硬件异常产生信号,除数为0、无效的存储访问等等。这些情况通常由硬件检测到,将其通知内核,然后内核产生适当的信号通知进程,例如,内核对正访问一个无效存储区的进程产生一个SIGSEGV信号。

1忽略  除了ISGKILL与SIGSTOP  2执行用户希望的动作   3 执行系统默认动作

发送信号的主要函数有kill和raise.kill既可以给自身发送信号也可以向其他进程发送信号。raise函数是向进程自身发送信号。alarm可以设置一个时间值,当所设置的时间到了时,产生一个ISGALARM信号,如果不扑捉此信号,则默认动作是终止该进程。pause函数使调用进程挂起直至捕捉到一个信号。int pause(void).

信号处理的主要方法有两种,一种是使用简单的signal函数,另一种是使用信号集函数组。

#include<signale.h>

void (*signal(int signo,void (*func)(int)))(int)  signal是一个函数指针,第一个是signo,第二个参数是一个函数指针  返回类型还是一个函数指针

理解为:

typedef void (*sighandler_t)(int)

sighandler_t signal(int signum,sighandler_t handler)   用ps aux查看进程号


共享内存:

创建加映射!当一个进程不再需要共享内存时,需要把它从进程地址空间中脱离。int shmdt(char*  shmaddr );

消息队列:

信号能传送的信息量有限,管道则只能传送无格式的字节流,这无疑会给应用程序开发带来不便。消息队列也叫做报文队列则客服了这些缺点。

消息队列就是一个消息的链表,可以把消息看做一个记录,具有特定的格式。进程可以向中按照一定的规则添加新消息。另一些进程则可以从消息队列中读走消息。

POSIX消息队列以及系统V消息队列。系统V消息队列目前被大量使用。

系统V消息队列是随内核持续的,只有在内核重启或者人工删除时,该消息队列才会被删除。

消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值。

key_t ftok(char* pathname,char proj);功能:返回文件名对应的键值   pathname:文件名  proj:项目名(不为0即可)

int  msgget(key_t key,int msgflg)

key:键值,由ftok获得。msgflg:标志位  IPC_CREATE   IPC_EXCL  IPC_NOWAIT 返回值:与键值key相对应的消息队列描述字。

创建新的消息队列条件:

没有与键值key相对应的消息队列并且msgflg中包含了IPC_CREATE标志位。   key参数为IPC_PRIVATE.

int   open_queue(key_t keyval)

{

 int qid;

  if((qid=msgget(keyval,IPC_CREATE))==-1)创建一个消息队列

 {

 RETURN -1;

}

 return(qid);

}

int msgsnd(int msqid,struct msgbuf* msgp,int msgsz,int msgflg)想消息队列中发送一条消息

struct  msgbuf

{

 long mtype;

char mtext[1];

};

int msgrcv(int msqid,struct msgbuf* msgo,int msgsz,long msgtyp,int msgflg)功能是从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构中,在成功地读取了一条消息以后,队列中的这条消息将被删除。


信号量:信号量与其他进程间通信方式不大相同,主要用途是保护临界资源。进程可以根据它判断是否能够访问某些共享资源,除了用于访问控制外,可以用于进程同步。

信号量是一个整数。二值信号量只能取0或1,类似于互斥锁。计数信号灯:信号灯的值可以取任意非负值。

0 0
原创粉丝点击