Loading

进程间通信和同步

进程间通信

创建新IPC对象需指定的mode常值:

常值 说明
S_IRUSR/S_IWUSR 用户读/写
S_IRGRP/S_IWGRP 组成员读/写
S_IROTH/S_IWOTH 其他用户读/写

管道

  1. 无名管道,单向数据流,常用于父子进程间通信。
int pipe(int fd[2]);

该函数返回两个文件描述符:fd[0]读,fd[1]写,即半双工管道。

  1. FIFO,单向数据流,每个FIFO有一个路径名与之关联,允许无亲缘关系的进程访问同一个FIFO,也称为有名管道。
// pathname:路径名
// mode:文件权限位
int mkfifo(const char *pathname, mode_t mode);
  1. 管道和FIFO属性
  • 描述符可指定O_NONBLOCK标志

  • 请求读出的数据量多于管道或FIFO中可用数据量,只返回可用数据量

  • 请求写入的数据字节数小于或等于PIPE_BUF,那么write操作保证是原子

  • O_NONBLOCK标志的设置对write操作的原子性影响:
    待写字节小于PIPE_BUF时
    a. 管道或FIFO中空间足,那么所有数据字节都写入;
    b. 管道或FIFO中空间不足,立即返回EAGAIN错误;
    待写字节大于PIPE_BUF时
    c. 管道或FIFO至少有1字节空间,写入能容纳的数据字节,并返回实际写入的字节数;
    d. 管道或FIFO已满,立即返回EAGAIN错误。

  • 系统对管道和FIFO的限制:
    a. OPEN_MAX:一个进程在任意时刻打开的最大描述符数,可通过limit命令修改;
    b. PIPE_BUF:可原子地写往一个管道或FIFO的最大数据量。

消息队列

消息队列具有随内核的持续性。

// 创建或打开消息队列
//oflag参数是O_RDONLY、O_WRONLY或O_RDWR之一,可按位或上O_CREAT、O_EXCL或O_NONBLOCK
//创建新队列是需指定mode和attr参数
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
// 关闭消息队列,但依然存在于系统中
int mq_close(mqd_t mqdes);
// 减少引用计数,引用计数为0时会从系统删除消息队列
int mq_unlink(const char *name);
// 发送消息到队列,prio指定优先级,需小于MQ_PRIO_MAX
int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio);
// 从队列接收消息,priop传出参数,放置优先级
ssize_t mq_receive(mqd_t mqdes, char *ptr, size_t len, unsigned int *priop);
// 异步事件通知,产生一个信号或创建一个线程来执行一个指定的函数
int mq_notify(mqd_t mqdes, const struct sigevent *notification);

共享内存区

mmap函数把一个文件或共享内存区对象映射到调用进程的地址空间。使用该函数有三个目的:

  • 使用普通文件以提供内存映射I/O
  • 使用特殊文件以提供匿名内存映射
  • 使用shm_open以提供无亲缘关系进程间的共享内存区
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t len);
// 返回一个整数描述符,用作mmap的第五个参数
int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name);
// 修改mmap后普通文件或共享内存区对象的大小
int ftruncate(int fd, off_t length);

同步

互斥锁

互斥锁静态分配static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;;动态分配调用pthread_mutex_init函数来初始化它。

int pthread_mutex_init(pthread_mutex_t *mptr, const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mptr);
int pthread_mutex_lock(pthread_mutex_t *mptr);
int pthread_mutex_trylock(pthread_mutex_t *mptr);
int pthread_mutex_unlock(pthread_mutex_t *mptr);

条件变量

int pthread_cond_init(pthread_cond_t *cptr, const pthread_condattr_t *attr);
int pthread_cond_destroy(pthread_cond_t *cptr);
int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);
// 唤醒一个线程
int pthread_cond_signal(pthread_cond_t *cptr);
// 唤醒全部线程
int pthread_cond_broadcast(pthread_cond_t *cptr);
// 到时唤醒
int pthread_cond_timewait(pthread_cond_t *cptr, pthread_mutex_t *mptr, const struct timespec *abstime);

信号量

  1. 有名信号量
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
int sem_close(sem_t *sem);
int sem_unlink(const char *name);
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 *valp);
  1. 无名信号量,又叫内存信号量
// share为0,则在同一进程的各个线程间共享,否则进程间共享
int sem_init(sem_t *sem, int shared, unsigned int value);
int sem_destroy(sem_t *sem);
posted @ 2024-08-05 17:02  songlh424  阅读(14)  评论(0)    收藏  举报