Chinaunix首页 | 论坛 | 博客
  • 博客访问: 584567
  • 博文数量: 92
  • 博客积分: 5026
  • 博客等级: 大校
  • 技术积分: 1321
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-28 11:04
文章分类

全部博文(92)

文章存档

2011年(9)

2010年(17)

2009年(12)

2008年(54)

我的朋友

分类: LINUX

2008-03-25 15:46:29

linux进程间通信
1. 管道。
  匿名一次性使用的,半双工。一个进程往输出端写管道,另一个进程从输入端读管道。
  int pipe(int fds[2]);
2. FIFO特别文件
  有名管道,作为特别文件存储于文件系统中。有名管道一旦建立就存在于文件系统中,除非显示的unlink
 
3. 消息队列、信号量和共享内存
   函数 msgget semget shmget  msgctl semctl shmctl
   每个ipc资源有两个唯一的标志与其相连 关键字和标识(关键字类似于文件名,标志类似于文件描述字用来访问资源的操作)
   关键字获得函数 key_t ftok(const char* path, int id)
  
   ipc_perm结构,当进程创建ipc资源时,内核存储了ipc资源的属主和组id和访问权限等信息。
   uid_t uid            当前有效用户id
   gid_t gid            当前有效组id
   cuid_t cuid          创建用户id
   cgid_t cgid     创建组id
   mode_t mode          访问权限
  
   ipc资源创建之后,可以长期存储在文件系统中,直到被删除或者系统重启。
   shell命令:ipcs -q -s -m   ipcrm
       
   a. 消息队列
   struct msqid_ds(消息队列相连的数据结构) {
   struct ipc_perm msg_perm;  该消息队列的属主和访问权限
   struct msg*    msg_first; 指向第一个消息的指针
   struct msg*     msg_last;  指向最后一个消息的指针
   msgqnum_t      msg_qnum;  当前消息的个数
   msglen_t        msg_qytes; 最大容量字节数
   pid_t           msg_lspid; 最后一个调用msgsnd的进程
   pid_t           msg_lrpid; 最后一个调用msgrcv的进程
   time_t          msg_stime; 最后发送时间
   time_t          msg_rtime; 最后接收时间
   time_t          msg_ctime; 最后修改时间
   }
  
   struct msg {
    struct msg* mas_next; 下个消息的指针
    long msg_type;        消息的类型
    caddr_t msg_sport;    消息正文地址
    sort msg_ts;          消息正文的大小
   }
  
   int msgget(key_t key, int msgflg);
   msgflg IPC_CREAT当系统不存在和key相连的消息队列时,就创建一个key为关键字的消息队列(用于创建一个新的队列)
       IPC_EXCL 和IPC_CREAT一起使用时,当已经存在队列时,则返回失败(防止关键字重复)
  
   int msgctl(int msgid, int cmd, struct msqid_ds* buf);
   控制消息队列cmd
   IPC_STAT   获得msgid的消息队列数据结果到buf中
   IPC_SET    设置buf中ipc_perm为消息队列的新值
   IPC_RMID   删除消息队列
  
   int msgsnd(int msgid, const void* msg, size_t size, int msgflag);
   ssize_t msgrcv(int msgid, void* msg, size_t size, long int msgtyp, int msgflag);
   size实际上是指正文段的大小,总大小应该是size+4字节,接收是同样的意思
  
   msgflag: IPC_NOWAIT
   msgsnd()为阻塞函数,当消息队列容量满或者消息个数满会阻塞,如果消息队列被删除,则EIDRM错误,被信号中断E_INTR。
              如果设置IPC_NOWAIT会返回-1并且置EAGAIN错误
  msgrcv() long int msgtyp  if == 0 接收第一个消息           
                            if > 0  接收类型等于msgtyp的第一个消息
                            if < 0  接收类型等于或者小于msgtyp绝对值的第一个消息
                           
  b。 信号量
  struct semid_ds {
   struct ipc_perm sem_perm;       包含信号量资源的属主和访问权限
   struct sem      *sem_base;      指向信号量集合的指针
   unsigned short  int sem_nsems;  集合中信号的个数
   time_t          sem_otime;      最后一次操作的时间
   time_t          sem_ctime;      最后一次修改的时间
  }
 
  struct sem {
  unsigned short semval;           当前信号量值 
  pid_t     sempid;                最后修改信号量的进程
  unsignde short semcnt;           等待进行p操作的进程数
  unsigned short semzcnt;          等待semval为0的进程数
  }
 
  int semget(key_t key, int semnum, int flag)
  semnum信号集合中有几个信号量
  flag IPC_CREAT IPC_EXCL
 
  semctl(int semid, int semnum, int cmd, union semun arg) 可以为信号量初始值,删除信号量设置权限等
  semnum 为信号量集合中的某个信号量操作
  cmd    SETVAL IPC_RMID
  union semun {
   short val;              设置信号量的值
   struct semid_ds* buf;   设置或者获得semid_ds结构
   unsigned short* array;  指向信号量的数组,用于集体初始化
  } arg;
  
 信号量操作
 int semop(int semid, struct sembuf* buf, int bufsize);
 struct sembuf {
  short semnum; 信号量集合中的信号量编号
  short val;    val>0进行v操作加val  val<0进行p操作减val val=0时阻塞等待信号量为0
  short flag;  IPC_NOWAIT IPC_UNDO当执行pv操作之后,进程突然终止没有进行相应的vp操作
 }buf; 
 
 c。共享存储
 shmget(key_t key, int size, int flag)
 size为n时表示获得或者创建这么大的共享段
 size为0时表示直接获得整个共享段
 size大于创建的共享段时,返回错误
 (创建时指定n, 获得时一般直接为 0)
 struct shmid_ds {
  struct ipc_perm shm_perm;
  size_t shm_segsz     大小
  pid)t shm_pid        最后操作的进程id
  pid)t shm_cpid       创建的进程id
  shmatt_t shm_nattch  当前连接数
  time_t shm_atime     最后调用shmat的时间
  time_t shm_dtime     最后调用shmdt的时间
  time_t shm_ctime     最后调用shmctl的时间
 }
 shmctl(int shmid, int cmd, struct shmid_d* buf);
 cmd  IPC_STAT IPC_SET IPC_RMID SHM_LOCK SHM_UNLOCKroot用户专用
 void* shmat(int shmid, const void* shmaddr, int flag);
 shmaddr一般为0,内核自动为程序一个连接到共享内存段的地址返回给进程
 flag  SHM_RDONLY SHM_RND(当shmaddr设置为自己的值时,shm_rnd标志设置后,将会对这个地址做适当的截断以适合系统的对齐)
 int shmdt(const void* shmaddr);
 
   
  
                           
阅读(1339) | 评论(0) | 转发(0) |
0

上一篇:linux进程和信号

下一篇: linux网络编程

给主人留下些什么吧!~~