Linux进程/线程间同步与通信

进程/线程间通信方式

  1. 管道 (进程和线程) 基于流,半双工,数据只能向一个方向流动,双方通信时需要建立两个管道,管道缓存区有限

    1. 无名管道 可用于具有亲缘关系的进程间通信

      1
      int pipe(int fildes[2]);
    2. 有名管道 可用于无血缘关系的进程间通信

  2. 信号 (进程)

    1
    2
    3
    #include <signal.h>
    void (*signal(int sig, void (*func)(int)))(int);
    int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
  3. 消息队列 (进程和线程) 消息的链表,存放在内核,有消息队列标识符标识.不需要同步机制.

    1
    2
    3
    4
    5
    #include <sys/msg.h>
    int msgget(key_t key, int msgflg);
    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
  4. 共享内存 (进程和线程) 多个进程可以访问同一块内存空间,和其它通信机制结合使用,达到进程间的同步和互斥 速度快

    1
    2
    3
    4
    5
    6
    #include <sys/ipc.h>
    #include <sys/shm.h>
    int shmget(key_t key, size_t size, int shmflg); //用来创建共享内存
    void *shmat(int shmid, const void *shmaddr, int shmflg); //将共享内存段连接到进程地址空间
    int shmdt(const void *shmaddr); //将共享内存段与当前进程脱离
    int shmctl(int shmid, int cmd, struct shmid_ds *buf); //用于控制共享内存
  5. 信号量 (进程和线程) 进程间或线程间同步 一个计数器,每次调用wait将使信号量值减一,如果信号量值为0,则wait将阻塞.每次调用post操作将使信号量值加1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <semaphore.h>
    sem_t *sem_open(const char *name, int oflag, ...);
    int sem_init(sem_t *sem, int pshared, unsigned value);
    int sem_close(sem_t *sem);
    int sem_destroy(sem_t *sem);
    int sem_wait(sem_t *sem);
    int sem_trywait(sem_t *sem);
    int semctl(int semid, int semnum, int cmd, ...);
    int semget(key_t key, int nsems, int semflg);
    int semop(int semid, struct sembuf *sops, size_t nsops);
  6. socket套接字 (进程和线程) 基于流 跨服务器

    1
    2
    3
    4
    5
    int socket(int family, int type, int protocol);
    int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
    int listen(int sockfd, int backlog);
    int accept(int sockfd, struct sockaddr *client_addr, socklen_t *len);
    int connect(int sock_fd, struct sockaddr *serv_addr,int addrlen);
  7. 互斥量 (线程) 线程同步方式 互斥锁,访问共享资源前加锁,访问完后释放互斥量,一次只能由一个线程运行 需要注意死锁

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <pthread.h>
    int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); //互斥量初始化
    int pthread_mutex_destroy(pthread_mutex_t *restrict mutex); //互斥量销毁
    int pthread_mutex_lock(pthread_mutex_t *mutex); //加锁
    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex); //解锁
    PTHREAD_MUTEX_NORMAL 一种标准互斥量类型,不做任何特殊的错误检查或死锁检测。
    PTHREAD_MUTEX_ERRORCHECK 此互斥量类型提供错误检查。
    PTHREAD_MUTEX_RECURSIVE 此互斥量类型允许同一线程在互斥量解锁之前对该互斥量进行多次加锁。递归互斥量维护锁的计数,在解锁次数和加锁次数不相同的情况下,不会释放锁。
    PTHREAD_MUTEX_DEFAULT 此互斥量类型可以提供默认特性和行为。
    int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr, int *restrict type); //得到互斥量类型属性
    int pthread_mutexattr_settype(const pthread_mutexattr_t *attr, int type); //设置互斥量类型属性
    1. 预防死锁:破环死锁产生的四个必要条件:互斥条件,不可剥夺条件,请求和保持条件,循环等待条件
    2. 避免死锁:每次资源分配前,应该计算此次分配资源的安全性,如果此次资源分配不会导致系统进入不安全状态,则分配资源,否则等待.算法:银行家算法
    3. 检查死锁:检测到死锁后通过资源剥夺,撤销进程,进程回退等方法解除死锁.
  8. 自旋锁 (线程) 线程同步方式 自旋锁不是通过休眠使进程阻塞,而是在获取锁之前一直处于忙等待阻塞状态(占用CPU),用于锁持有时间短,并且线程不希望在重新调度上花费大量成本的情况下

    1
    2
    3
    4
    5
    6
    #include <pthread.h>
    int pthread_spin_init(pthread_spinlock_t *lock, int pshared); //初始化锁
    int pthread_spin_destroy(pthread_spinlock_t *lock); //销毁锁
    int pthread_spin_unlock(pthread_spinlock_t *lock); //解锁
    int pthread_spin_lock(pthread_spinlock_t *lock); //加锁
    int pthread_spin_trylock(pthread_spinlock_t *lock);
  9. 条件变量 (线程) 常和互斥锁一起使用,使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程解开相应的互斥锁并等待条件发生变化,一旦其它线程改变了条件变量,条件变量将唤醒一个或多个被此条件变量阻塞的线程,这些线程重新锁定互斥锁并重新测试条件是否满足.

    1
    2
    3
    4
    5
    6
    7
    #include <pthread.h>
    int pthread_cond_init(pthread_cond_t *cv,const pthread_condattr_t *cattr); //初始化条件变量
    int pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex); //等待条件变量
    int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mp, const structtimespec * abstime); //等待条件变量到某个时间
    int pthread_cond_signal(pthread_cond_t *cv); //通知条件变量的单个线程
    int pthread_cond_broadcast(pthread_cond_t *cv); //通知条件变量的多个线程
    int pthread_cond_destroy(pthread_cond_t *cv); //销毁条件变量
  10. 读写锁 (线程) 线程同步方式 三种状态 1.读模式加锁 2.写模式加锁 3.不加锁 一次只能有一个线程占用写模式的读写锁 但可以有多个线程同时占有读模式的读写锁

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <pthread.h>
    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); //销毁锁
    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); //初始化锁
    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); //解锁
    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); //读加锁
    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); //写加锁
    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abstime);
    int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abstime);
  11. 线程信号量 (线程)

  12. 全局变量 (线程)

管道

管道

消息队列

消息队列

信号量

信号量

共享内存

共享内存