uc10

来源:互联网 发布:新旧系统数据迁移方案 编辑:程序博客网 时间:2024/06/06 00:21
回顾:
  信号 - 信号集 sigset_t 及其相关函数
   sigemptyset sigaddset sigdelset sigismember
   信号屏蔽 - sigprocmask
   信号注册增强版函数 - sigaction
    SA_SIGINFO sa_flags
    sa_sigaction 函数指针
  IPC - 有名管道
   mkfifo - 创建管道文件 命令/函数
   按照 操作普通文件的方式操作 管道
今天:
   无名管道:
    管道文件由 内核管理
    只能用于 fork()创建的 父子进程之间。
    借助pipe() 创建一个读管道,一个写管道。
  XSI IPC结构 - 共享内存、消息队列、信号量集
   XSI IPC 包括共享内存、消息队列、信号量集,隶属于同一个规范,有着共同的特征。
   每个XSI IPC结构 都是在内核中存储和维护的,用ipcs 命令可以查看,用ipcrm 命令可以删除。
  ipcs -a 查看全部IPC结构
       -m 查看共享内存
       -q 查看消息队列
       -s 查看信号量集
  ipcrm 用法和ipcs 类似,但 后面要跟上 ID。
   每个XSI IPC结构都有两个东西定位:外部到内核要用key,内核中使用ID标识。
  key的生成:
   key的类型key_t,其实是一个长整形,有3种方法得到key:
   1 使用宏 IPC_PRIVATE 做key,但这种方式无法实现 进程间的通信(私有),极少使用。
   2 把所有的key定义在一个头文件中,用宏定义。
   3 使用ftok()函数生成key,参数:真实存在的路径和项目编号(0-255)。
  ID的生成:
   IPC结构在内核中都用ID做唯一标识,创建/获取ID都有对应的函数,比如:
   int shmid = shmget(key,...);
   int msgid = msgget(key,...);
   调用XXXget()时,都有一个flags,创建时的值为
   权限|IPC_CREAT|IPC_EXCL
    IPC_CREAT - 创建
    IPC_EXCL - 如果存在会返回错误
    和O_CREAT O_EXCL 类似。
  IPC结构都有一个特殊的操作函数,提供查询、修改和删除的功能。
 函数名:XXXctl(),比如:shmctl() msgctl()
   参数cmd提供功能:
   IPC_STAT - 查询IPC结构的属性/状态
   IPC_SET - 修改IPC结构的相关属性,但只能修改权限
   IPC_RMID - 删除IPC结构,按ID删除
 
  IPC结构 - 共享内存
   每个进程 内存独立的,无法直接互访。共享内存就是内核管理一段内存(物理内存),这段物理内存允许 每个进程进行映射。
   编程步骤:
   1 系统创建/获取共享内存(拿到物理内存)
     ftok()-> key
     shmget() -> 创建/获取共享内存,返回ID
   2 挂接共享内存(映射) shmat()
   3 使用共享内存
   4 脱接共享内存(解除映射) shmdt()
   5 如果共享内存不再被使用,可以删除。shmctl()
  共享内存的优缺点:
   优点:速度最快的IPC,高效率
   缺点:如果有多个进程写数据,将会产生覆盖问题,导致数据的错误和不完整。
   
  消息队列 - 有一个队列,队列中存放各种消息。每个进程可以把数据 封存在消息中,再放入队列。
  每个进程都可以 拿到消息队列,再从中取出/放入消息。
  消息队列 不会 产生覆盖问题,但 需要考虑队列长度。
  消息队列的编程步骤:
   1 生成key ,使用ftok()或用头文件定义
   2 创建/获取消息队列 msgget()
   3 发送/接收 消息 msgsnd() / msgrcv()
   4 如果不会再被使用(所有进程都不用)可以删除
    msgctl()
  相关函数:
    msgget()用法和shmget()基本一样。获取时flag为0,新建flag为 权限|IPC_CREAT|IPC_EXCL
    msgctl()用法和shmctl()基本一样。
    int msgsnd(int msgid,void* p,size_t size,
    int flag)
    msgid 就是消息队列,p是发送的消息的首地址,size是发送消息的大小,flag为0代表阻塞,为IPC_NOWAIT代表非阻塞。(消息满了以后是否等待)
    成功返回0,失败返回-1
    ssize_t msgrcv(int msgid,void* buf,
     size_t size,int msgtype,int flag)
     msgid、flag和msgsnd()一样
     buf是用来接收消息的首地址
     size是sizeof(buf)
     msgtype 代表消息的类型,消息分为:
      无类型消息和有类型消息。
    无类型消息 可以是任意类型,比如:整数、字符串、浮点...
    无类型消息的取出 遵循队列的基本准则: FIFO。
    有类型消息,类型必须是一个结构体:
    struct 自定义名字{
      long mtype;//消息类型,必须有,格式固定
      char msg[];//数据
    };
    数据是:char数组,长度和名称可以自定义
          用 其他类型也可以
    mtype取值时,必须 大于0。(赋值时不能<=0)
    接收数据时可以按消息类型接收,msgrcv()中的第四个参数可以指定接收消息的类型:
    =0 代表接收任意类型的消息(遵循先入先出)
    >0 代表接收特定类型的消息(mtype=值)
    <0 代表接收类型小于等于 参数绝对值的消息
   次序从小到大,如果类型相同,按在队列中的位置
  有类型消息 在计算发送和接收的size时,可以不计算类型所占的空间。(sizeof(struct)-4)
  练习&作业:
   1 为综合案例做准备工作:
    文件、进程、信号、消息队列 必定会用到。
    内存分配 可以考虑使用
   2 使用信号ctl+c实现退出进程时删除消息队列。
⑿藕拧⑾⒍恿?必定会用到。
    内存分配 可以考虑使用
   2 使用信号ctl+c实现退出进程时删除消息队列。

0 0
原创粉丝点击