Linux进程通信---学习笔记(二)

1.内存映射

①内存映射就是把文件中的内容,复制到内存中去。
②内存映射函数:void *mmap(void *start,size_t length,int port,int flags,int fd,off_t offset)
参数说明:1.void *start :  一般该参数都为0
             2.size_t length : 文件长度
             3.int port :PROT_READ | PROT_WRITE 可读、可写
             4. int flags:MAP|SHARED一个进程改了,其映射该文件的进程也看得见,但是没有写入文件,要写入文件需调用 msync 
             5.int fd:文件描述符
             6.off_t offset:文件内从开始的位置
③解除映射函数:int munmap(void *start,size_t length)
④举例:

#include <stdio.h>
#include <unistd.h>/*close函数*/
#include <sys/mman.h>
#include <fcntl.h>/*open函数*/
#define NUM (10)
typedef struct
{
    int no;
    char data[30];
10  }RECORD;
11  int main()
12  {
13      RECORD *mapped;
14      int filde = open("records.dat", O_RDWR);
15      mapped = (RECORD *)mmap(0,
16                              NUM * sizeof(RECORD),
17                              PROT_READ | PROT_WRITE,
18                              MAP_SHARED,
19                              filde,
20                              0);
21      mapped[5].no = 8888;
22      sprintf(mapped[5].data, "Record-%d/n", mapped[5].no);
23      msync((void*)mapped, NUM * sizeof(RECORD), MS_ASYNC);
24      munmap((void*)mapped, NUM * sizeof(RECORD));
25      close(filde);
26      return 0;
27  }

 

2.内存共享

①创建 shmget
原型:int shmget ( key_t key, int size, int shmflg );
参数说明:
        key:共享内存的键值。
        size:建立共享内存的长度。
        shmflg:
        IPC_CREAT:如果共享内存不存在,则创建,否则打开。
        IPC_EXCL:如果共享内存不存在,则建立,否则报错。
返回值:如果成功,返回共享内存段标识符。如果失败,则返回-1:

②连接 shmat
原型:void * shmat ( int shmid, char *shmaddr,int shmflg);
参数说明:
        shmid:共享内存标识符;
        shmaddr:进程映射地址,通常为null;
        shmflg:映射地址空间访问属性,例如SHM_RDONLY;
返回值:
        如果成功,则返回共享内存段连接到进程中的地址。如果失败,则返回-1:
        errno = EINVAL (无效的IPC ID 值或者无效的地址)
        ENOMEM (没有足够的内存)
        EACCES (存取权限不够)

③解除 shmdt
调用原型:int shmdt ( char *shmaddr );
返回值:如果失败,则返回-1:errno = EINVAL (无效的连接地址)

④控制(用来删除) shmctl
函数原型:int shmctl(int shm_id, int cmd,struct shmid_ds *buf);
参数说明:
         shm_id:共享内存标识符
         cmd:将要采取的动作,可以取值IPC_STAT、IPC_SET、IPC_RMID,分别表示把shmid_ds结构中的数据设置为共享内存的当前关联值、按照shmid_ds设置共享内存和删除共享内存段。
         buf:保存共享内存的模式状态。
⑤举例说明

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
    int pid,shmid;//后者为共享内存识别代号
    char *write_address;
10      char *read_address;
11      struct shmid_ds dsbuf;
12      if((shmid=shmget(IPC_PRIVATE,32,0))<0)//分配共享内存,创建
13      {
14          printf("shmid共享内存分配出现错误。/n");
15          exit(1);
16      }
17      else
18          printf("shmid共享内存分配成功,共享内存识别代号为:%d。/n",shmid);
19      if((pid=fork())<0)
20      {
21          printf("fork函数调用出现错误!/n");
22          exit(2);
23      }
24      else if(pid>0)//父进程,向共享内存中写入数据
25      {
26          printf("父进程的ID是:%d/n",getpid());
27          write_address=(char *)shmat(shmid,NULL,0);//连接共享内存
28          if((int)write_address==-1)
29          {
30              printf("shmat连接共享内存错误。/n");
31              exit(3);
32          }
33          else
34          {
35              printf("shmat连接共享内存成功。/n");
36              strcpy(write_address,"我是写入共享内存的测试数据");//将数据写入共享内存
37              printf("写入共享内存的信息为“%s”。/n",write_address);
38              if((shmdt((void *)write_address))<0)//断开与共享内存的连接
39                  printf("shmdt共享内存断开错误。/n");
40              else
41                  printf("shmdt共享内存断开成功。/n");
42              sleep(2);
43              return;
44          }
45      }
46      else//子进程,从共享内存中读取数据
47      {
48          sleep(2);//等待父进程写入共享内存完毕
49          printf("子进程ID是:%d/n",getpid());
50          if((shmctl(shmid,IPC_STAT,&dsbuf))<0)//将shmid相关的数据结构中各个元素的当前值放入由dsbuf指向的结构中
51          {
52              printf("shmctl获取共享内存数据结构出现错误。/n");
53              exit(4);
54          }
55          else
56          {
57              printf("shmctl获取共享内存数据结构成功。/n建立这个共享内存的进程ID是:%d/n",dsbuf.shm_cpid);
58              printf("该共享内存的大小为:%d/n",dsbuf.shm_segsz);
59              if((read_address=(char *)shmat(shmid,0,0))<0)//连接共享内存
60              {
61                  printf("shmat连接共享内存出现错误。/n");
62                  exit(5);
63              }
64              else
65              {
66                  printf("自共享内存中读取的信息为:“%s”。/n",read_address);
67                  printf("最后一个操作该共享内存的进程ID是:%d/n",dsbuf.shm_lpid);
68                  if((shmdt((void *)read_address))<0)//断开与共享内存的连接
69                  {
70                      printf("shmdt共享内存断开错误。/n");
71                      exit(6);
72                  }
73                  else
74                      printf("shmdt共享内存断开成功。/n");
75                  if(shmctl(shmid,IPC_RMID,NULL)<0)//删除共享内存及其数据结构
76                  {
77                      printf("shmctl删除共享内存及其数据结构出现错误。/n");
78                      exit(7);
79                  }
80                  else
81                      printf("shmctl删除共享内存及其数据结构成功。/n");
82                  exit(0);
83              }
84          }    
85      }
86  }

 

3.消息队列

①概述
cut1

②函数
创建
int msgget (key_t key, int flag)
—key:返回新的或已有队列的ID。
—flag:通常取值IPC_CREATE。

添加消息
int msgsnd (int msqid, struct msgbuf *msgp,size_t msgsz, int flag)
—msqid:消息队列的队列ID;
—msgp:消息内容所在的缓冲区;
—msgsz:消息的大小;
—msgflg:控制消息队列满或者到达系统上限将发生的事情,例如:设置IPC_NOWAIT则消息不发送并返回-1;清除IPC_NOWAIT则发送进程挂起直到消息队列腾出空间后返回。

接收
int msgrcv (int msqid, struct msgbuf *msgp,size_t msgsz,long msgtyp, int flag)
—msqid:消息队列的引用标识符;
—msgp:接收到的消息将要存放的缓冲区;
—msgsz:消息的大小,不包含消息类型;
—msgtyp:期望接收的消息类型,一般取值0;
—msgflg:没有相应消息可供接收时应发生的事情,例如:IPC_NOWAIT。

控制(删除)
int msgctl(int msqid,int cmd,struct msqid_ds *buf);

③举例

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
    int pid,msqid;//后者为消息队列识别代号
10      struct msgbuf
11      {
12          long mtype;//消息类型
13          char mtext[20];//消息内容
14      }send_buf,receive_buf;
15      if((msqid=msgget(IPC_PRIVATE,0700))<0)//建立消息队列
16      {
17          printf("msgget建立消息队列失败。/n");
18          exit(1);
19      }
20      else
21          printf("msgget建立消息队列成功,该消息队列识别代号为%d。/n",msqid);
22      if((pid=fork())<0)
23      {
24          printf("fork()函数调用失败!/n");
25          exit(2);
26      }
27      else if(pid>0)//父进程,发送消息到消息队列
28      {
29          send_buf.mtype=1;
30          strcpy(send_buf.mtext,"My test information");
31          printf("发送到消息队列的信息内容为:%s/n",send_buf.mtext);
32          if(msgsnd(msqid,&send_buf,20,IPC_NOWAIT)<0)//发送send_buf中的信息到msqid对应的消息队列
33          {
34              printf("msgsnd消息发送失败。/n");
35              exit(3);
36          }
37          else
38              printf("msgsnd消息发送成功。/n");
39          sleep(2);
40          exit(0);
41      }
42      else//子进程,从消息队列中接收消息]
43      {
44          sleep(2);//等待父进程发送消息完成
45          int infolen;//读到的信息数据长度
46          if((infolen=msgrcv(msqid,&receive_buf,20,0,IPC_NOWAIT))<0)//自消息队列接收信息
47          {
48              printf("msgrcv读取信息错误。/n");
49              exit(4);
50          }
51          else
52              printf("msgrcv读取信息成功。/n");
53          printf("自消息队列读取到的内容为%s,共读取%d个字节。/n",receive_buf.mtext,infolen);
54          if((msgctl(msqid,IPC_RMID,NULL))<0)//删除msqid对应的消息队列
55          {
56              printf("msgctl函数调用出现错误。/n");
57              exit(5);
58          }
59          else
60          {
61              printf("识别代号为%d的消息队列已经被成功删除。/n",msqid);
62              exit(0);
63          }
64      }
65  }

 

4.信号量

①semget
功能:创建一个新信号量或取得一个已有信号量的标志符
函数原型:int semget(key_t key,int nsems,int semflg);
“key” 参数
—预定义常数IPC_PRIVATE
—约定的关键字
—ftok函数
“semflg” 参数
—设置访问权限(低9位)
—IPC_CREAT, IPC_EXCL 按位或
“nsems”
—指定需要的信号量数目,几乎总是取值为1。

例:sem_id = semget((key_t)1234, 1,0666 | IPC_CREAT);

②semop
功能:改变信号量的值
函数原型为:int semop(int semid,struct sembuf *sops,size_t nsops);
“sops” 参数
struct sembuf
{
    unsigned short sem_num; /* 信号量编号*/
    short sem_op;
    /* 信号量操作*/
    short sem_flg;
    /* 操作标志*/
}
nsops参数
结构数组的元素个数
sem_flg
sem_flg用于对操作进行适当的控制,主要有2个控制标志。
IPC_NOWAIT:当指定的操作不能完成时,进程不等待立即返回,返回值为-1,errno置为EAGAIN。
SEM_UNDO(建议):进程退出时,执行信号量解除(undo)操作。

P():
int semaphore_p(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; /* P() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_p failed/n");
return(0);
}
return(1);
}

V():
static int semaphore_v(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; /* V() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1)
{
fprintf(stderr, "semaphore_v failed/n");
return(0);
}
return(1);
}

③semctl
功能:控制,删除
函数原型:int semctl(int semid,int semnum,int cmd,union semun arg);
参数说明:
int semid:信号标识符
int semnum:设置为0
int cmd:信号集操作
union semun
{
    int val;
    /*用于SETVAL命令,指明要设置的值*/
    struct semid_ds *buf;
    /*用于IPC_STAT/IPC_SET命令,用来存放信号量集合数据结构*/
    unsigned short *array;
    /*用于GETALL/SETALL命令,用来存放所获得的或是要设置信号量集合中所有信号量的值*/
} arg;
“cmd”parameter:
IPC_RMID:删除信号量集合
SETVAL:设置信号量集合中由semnum指定的单个信号量的值(设为arg.val)

④set

int set_semvalue(void)
{
    union semun sem_union;
    sem_union.val = 1;
    if (semctl(sem_id, 0, SETVAL, sem_union) == -1)
        return(0);
    return(1);
}

⑤del

void del_semvalue(void)
{
    union semun sem_union;
    if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
        fprintf(stderr, "Failed to delete semaphore/n");
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值