进程间通信

来源:互联网 发布:新版淘宝怎么添加好友 编辑:程序博客网 时间:2024/05/16 09:10
相关函数和数据结构在源代码 ipc/sem.c  和 include/linux/sem.h  中。

Sturct sem {
Short semval;
Ushort sempid;
};


信号量集合描述符是一个名字semid_ds结构体
Struct semid_ds {
Struct ipc_perm se_perm;
…..
Struct sem_queue *sem_pending;
Struct sem_queue **sem_pending_last;
Ushort sem_nsems;
};



信号量集合的创建和检索
Int semget(key_t key,int nsems,int semflg);
Key:
Names:要创建的信号量集合中包含信号量的个数。
Semflg:指定信号量集合的访问权限和操作模式。
0400
0200
IPC_CREAT
IPC_EXCL


信号量的PV操作
Int semop(int semid,struct sembuf *sops,unsigned nsops);
Semid:要实施pv操作的信号量集合标识号
Sops:指向信号量操作数组的指针
Nsops:本次实施操作的信号量个数




信号量操作等待队列


信号量控制操作
Int semctl(int semid,int semnum,int cmd,union semunarg);







共享内存基本原理
在多任务操作系统中,不允许用户进程直接访问物理内存空间,每个进程只能访问自己的虚拟空间,因此,linux采用了内存映射技术把共享内存的内存区域映射到有关进程的虚拟存储空间,是他成为虚拟存储空间的一部分,进而进程就可以对这个虚拟内存区域快速的直接读写。

当进程间使用共享内存进行通信时,首先要有一个进程向系统申请建立共享内存空间,内存空间建立以后,其他进程需要访问它时,同样由系统把它映射到这些进程的虚拟空间中。在linux中把共享内存映射到一个进程的虚拟存储区的过程,进程与共享内存的结合(attach),使用共享内存结束时,进程要脱离与共享内存的联系(detach)。

每个共享内存区域由一个数据结构记录着他的管理信息,为共享内存标识符,该描述符被定义为shmid_ds结构体:
Struct  shmid_ds {
Struct ipc_perm shm_perm;
Int shm_segsz;
Time_t shm_atime;
Time_t shm_dtime;
Time_t shm_ctime;
Usigned short shm_cpid;
Usigned short shm_lpid;
Short shm_nattch;
Usigned short shm_npages;
Struct vm_area_struct *attaches;
};


共享内存的创建
 int   shmget(key_t key ,intsize ,int shmflg);
 参数:
 Key:指出要创建或获取标识的信号量集合的键值,他是system_V识别IPC通信机制中对象的一种方式,它可以使用符号常量IPC_PRIVATE由系统给定,也可以在程序中由用户给定。
Size : 指出共享内存空间的大小(页的整数倍)。
Shflag:指定共享内存的访问权限与操作特性,IPC_CREAT(创建),IPC_EXCL(如果已创建,则不再创建)。
返回值:成功返回共享内存的标识号,失败返回-1



共享内存的控制操作
Shmctl(int shmid,int cmd,struct_ds *buf);
参数:
Shmid:控制的操作对象
Cmd:操作动作,IPC_STAT、IPC_SET,IPC_RMID
Buf:用于传递数据


共享内存的结合
int shmat(int shmid,char *shmaddr,int shmflg);
参数:
Shmid:要结合的共享内存标识号
Shmaddr:进行指定的共享内存在进程虚拟空间的起始地址,0表示由系统在进程虚拟存储空间分配的乖哦纳西内存区域。
Shmflg:SHM_RDONLY只读,0可读可写
返回值:成功返回共享内存在进程虚拟空间的首地址,失败0


共享内存的分离
int shmdt(char *shmaddr);
shmaddr:指出进程虚拟空间中共享内存的首地址。
返回值:成功返回0,失败返回-1.





管道的概念

数据在管道中是以字符流的形式传送的,即以字节为单位的顺序数据。

 

Linux把管道看作是一种文件,采用文件管理的方式对管道进行管理,但是管道不使用外存,而是使用物理内存存放传送的数据。

 

无名管道只能在父子进程之间进行通信

有名管道可以在任意进程间使用

 

Linux管道可以在终端命令行中使用,也可以在程序中使用。

 

 

无名管道

创建:

#include

Int pipe(int filedes[2]);

参数:

Filedes[0]:读取管道文件的标识号

Filedes[1]: 写入管道的文件标识号

在管道建立后,在程序中就可以使用读写文件函数,如readwrite函数,从管道中读取和写入数据。

 

在父子进程进行通信的时候,要先用父进程pipe()创建管道,然后用fork()创建子进程,不然子进程不能继承到父进程的管道资源,导致父子进程间不能通信。

 

通信时,可以由父进程用writefiledes[1])写入数据,子进程用readfiledes[0])读出数据,管道通信方向一旦建立以后将不能在更改,所以无名管道通信时单工的通信方式。

父进程的filedes[0]不用,可以使用closefiledes[0])关闭,子进程的filedes[1]也一样。

 

Linux中,管道缓冲区大小有全局符号常量PIPE_BUF确定,缺省值是一个物理页面,4k,在/include/linux/limits.h中定义如下:

#define PIPE_BUF  4096

 

 

 

命名管道

命名管道完全纳入文件系统进行管理,他是linux的一种特殊文件,具有完整的文件属性,所以称为FIFO文件。

 

命名管道和无名管道一样使用内存缓存区进行数据的传送。

命名管道的建立:

#incluide

Int mkfifo(const char *path,mode_tmode);

Path: 指明创建命名管道的路径和文件名

Mode:指明管道的访问权限

返回值:成功0,失败负值

 

Mknodpath,modelS_FIFO,0);

 

 

创建命名管道成功以后,其他进程就可以像操作普通文件一样对管道进程操作,如readwriteclose,但是lseek不能对管道文件进行操作。






 

Intmsgget(key_t key,int magflg);

 

 

Intmsgctl(int msqid,int cmd,struct msqid_ds *buf);

 

 

Intmsgsend(int msgid,struct msgbuf *msgp,int msgsz,intmsgopt);

Intmsgrcv(int msgid ,struct msgbuf *msgp,int msgsz,int msgtyp,intmsgopt);

 

 

 

 




0 0
原创粉丝点击