posix:
POSIX(Portable Operating System Interface for Computing Systems)是由IEEE 和ISO/IEC 开发的一簇标准。该标准是基于现有的UNIX 实践和经验,描述了操作系统的调用服务接口,用于保证编制的应用程序可以在源代码一级上在多种操作系统上移植运行。它是在1980 年早期一个UNIX 用户组(usr/group)的早期工作的基础上取得的。该UNIX 用户组原来试图将AT&T 的系统V 和Berkeley CSRG的BSD 系统的调用接口之间的区别重新调和集成,从而于1984 年产生了/usr/group 标准。1985 年,IEEE操作系统技术委员会标准小组委员会(TCOS-SS)开始在ANSI 的支持下责成IEEE 标准委员会制定有关程序源代码可移植性操作系统服务接口正式标准。到了1986 年4 月,IEEE 就制定出了试用标准。第一个正式标准是在1988 年9 月份批准的(IEEE 1003.1-1988),也既以后经常提到的POSIX.1 标准。
System V:
System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支。它最初由 AT&T 开发,在1983年第一次发布。一共发行了4个 System V 的主要版本:版本1、2、3 和 4。System V Release 4,或者称为SVR4,是最成功的版本,成为一些UNIX共同特性的源头,例如 ”SysV 初始化脚本“ (/etc/init.d),用来控制系统启动和关闭,System V Interface Definition (SVID) 是一个System V 如何工作的标准定义。
AT&T 出售运行System V的专有硬件,但许多(或许是大多数)客户在其上运行一个转售的版本,这个版本基于 AT&T 的实现说明。流行的SysV 衍生版本包括 Dell SVR4 和 Bull SVR4。当今广泛使用的 System V 版本是 SCO OpenServer,基于 System V Release 3,以及SUN Solaris 和 SCO UnixWare,都基于 System V Release 4。
System V 是 AT&T 的第一个商业UNIX版本(UNIX System III)的加强。传统上,System V 被看作是两种UNIX"风味"之一(另一个是 BSD)。然而,随着一些并不基于这两者代码的UNIX实现的出现,例如 Linux 和 QNX, 这一归纳不再准确,但不论如何,像POSIX这样的标准化努力一直在试图减少各种实现之间的不同。
POSIX IPC函数汇总
消息队列 | 信号量 | 共享内存区 | |
---|---|---|---|
头文件 | |||
创建,打开或删除IPC的函数 | mq_open mq_close mq_unlink |
sem_open sem_close sem_unlink sem_init sem_destroy |
shm_open shm_unlink |
控制IPC操作的函数 | mq_getattr mq_setattr |
ftruncate fstat |
|
IPC操作函数 | mq_send mq_receive mq_notify |
sem_wait sem_trywait sem_post sem_getvalue |
mmap munmap |
说明 | mq_open | sem_open | shm_open |
---|---|---|---|
只读 只写 读写 |
O_RDONLY O_WRONLY O_RDWR |
O_RDONLY O_RDWR |
|
若不存在就创建 排他性创建 |
O_CREATE O_EXCL |
O_CREATE O_EXCL |
O_CREATE O_EXCL |
非阻塞模式 若以存在则截断 |
O_NONBLOCK | O_TRUNC |
这些常值在中定义
#define FILE_MODE(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
常值 | 说明 |
---|---|
S_IRUSE S_IWUSE |
用户读 用户写 |
S_IRGRP S_IWGRP |
组成员读 组成员写 |
S_IROTH S_IWOTH |
其他用户读 其他用户写 |
消息队列 | 信号量 | 共享内存区 | |
---|---|---|---|
头文件 | |||
创建,打开或删除IPC的函数 | msgget | semget | shmget |
控制IPC操作的函数 | msgctl | semctl | shmctl |
IPC操作函数 | msgsend msgrcv |
semop | shmat shmdt |
管道和fifo
#include <unistd.h>
int pipe(int fd[2]);//成功返回0,失败返回-1
//fd[0]读,fd[1]写
//单向管道,只能一边读另一边写
popen和pclose
#include <stdio.h>
FILE* popen(const char* command, const chat* type);
int pclose(FILE* stream);
/*
command是一个shell标准命令行
如果type为r,那么调用进程读进command的标准输出
如果type为w,那么调用进程读进command的标准输入
*/
FIFO
#include <sys/types.h>
#incluse <sys/stat.h>
int mkfifo(const char* pathname,mode_t mode);
//pathname:路径名
//mode:权限位,默认(O_CREATE | O_EXCL)
//可以使用open打开,read和write等读写函数
//读写具有原子性
POSIX消息队列
#include <mqueue>
struct mq_attr{
long mq_flags;//阻塞标志, 0或O_NONBLOCK
long mq_maxmsg;//最大消息数
long mq_msgsize;//每个消息最大大小
long mq_curmsgs;//当前消息数
};
mqd_t mq_open(const char* name,int flag, ...);//成功返回描述符,失败返回-1
/*
name:地址
flag:属性
第四个参数可以传递mq_addr指针,api只关注mq_maxmsg和mq_msgsize,
*/
//设置和获取消息队列的属性
int mq_getattr(mqd_t mqdes,struct mq_attr* attr);//只使用mq_flags参数,
int mq_setattr(mqd_t mqdes,const struct mq_attr* attr, struct mq_attr* oattr);
//msg_prio优先级等级,可以值为空
int mq_send(mqd_t mqdes, const char *msg_ptr,size_t msg_len, unsigned int msg_prio);
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,size_t msg_len, unsigned int *msg_prio);
int mq_notifiy(mqd_t mqdes,const struct sigevent* notification);//信号通知
int mq_unlink(const char *name);//减少一个内核计数
System V消息队列
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
//key:既可以是ftok的返回值,也可以是常值IPC_PRIVATE,msgflg权限属性
int msgget(key_t key, int msgflg);//创建一个新的消息队列或者访问一个已存在的消息队列
struct msgbuf{
long type;
char mtext[1];
}//msgp默认类型,可自定义
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);//成功返回0,失败返回-1
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);//成功返回写入字节数,失败返回-1
int msgctl(int msqid, int cmd, struct msqid_ds *buf);//控制操作
/*
IPC_RMID 从系统中删除由ms?id指定的消息队列。当前在该队列上的任何消息都被丢弃。我们已在图3-7中看到过这种操作的例子。对于该命令而言,msgctl函数的第三个参数被忽略。
IPC_SET 给所指定的消息队列设置其msqid_ds结构的以下4个成员:msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_qbytes。它们的值来自由buff参数指向的结构中的相应成员。
IPC_STAT (通过buff参数)给调用者返回与所指定消息队列对应的当前msqid_ds结构。
*/
posix信号量
有名信号量(基于文件) 基于内存的信号量
sem_open() sem_init()
\ /
sem_wait()
sem_trywait()
sem_post()
sem_getvalue()
/ \
sem_close() sem_destroy()
sem_unlink()
有名信号量既可以用于线程间同步,也可以用于进程间同步,
有名信号量(基于文件)
#include <semapore.h>
//打开一个有名信号量
sem_t* sem_open(const char* name, int oflag,...
/*mode_t mode, unsigned int value*/);
/*
name:文件名称
oflag:文件权限属性
mode:用户权限属性
value:信号初始值
返回值:成功返回指向信号量的指针
*/
//关闭信号量
int sem_close(sem_t *sem);
int sem_unlink(const char *name);
基于内存的信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
//获取信号量
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
//投入信号量
int sem_post(sem_t *sem);
//获取信号量的数量
int sem_getvalue(sem_t *sem, int *sval);
//成功返回0,失败返回-1
System V 信号量
共享内存
posix共享内存
//创建共享内存区或打开一个已经存在的共享内存区
int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name);
//oflag:文件权限属性
//mode:用户权限属性
//成0败-1
//ftruncate会将参数fd指定的文件大小改为参数length指定的大小。
int ftruncate(int fd, off_t length);
//获取文件状态
int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
mmap可用于进程间的通信,也可用于文件映射(零拷贝技术)
- 内存映射文件(通过open函数获取的fd)
- 共享内存区对象(通过shm_open获取的fd)
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
/*
addr:告诉内核映射的起始地址,一般置为null,表示由内核分配内存
length:映射长度
port:
PROT_READ:可读
PROT_WRITE:可写
PROT_EXEC:可执行
PROT_NOTE:不可访问
flags:
MAP_SHARED:变动是共享的(对与参与映射的进程和底层文件对象的修改都是共享的)
MAP_PRIVATE:变动是私有的(对数据做的修改只对该进程可见,不修改底层对象数据)
MAP_FIXED:准确的解释addr参数(不建议使用)
fd:文件描述符
offset:起始偏移地址
返回值:返回映射内存的起始地址
*/
int munmap(void *addr, size_t length);//释放共享内存
//如果对mmap进行修改后想要立即同步底层文件对象数据(例如硬盘文件对象数据),可调用msync
int msync(void *addr, size_t length, int flags);
/*flags:
MS_ASYNC:执行异步读写
MS_SYNC:执行同步读写
MS_INVALIDATE:使高速缓冲区的数据失效
返回值:成0败-1
*/