进程间通信

1. 竞争:
            当多个进程同时读写共享数据时,会出现进程竞争。
2. 临界区:
            对共享内存进行访问的程序片段成为临界区。
3. 睡眠与唤醒:
             sleep() :将进程睡眠,即阻塞
             wakeup(a):将a进程唤醒,即从阻塞态转为就绪或者运行态
4. 信号量:
             使用整型变量来累计唤醒次数,信号量的取值为0或者正值。
             信号量有两种操作:down和up(或者说P和V操作)
                  down(&mutex)表示将临界区加锁,禁止其他进程访问。当mutex为0时,该进程sleep;当mutex为正数时,mutex-1,且进程进入临界区。
                  up(&mutex)表示将临界区解锁,mutex从0变为1,表示允许其他进程进行访问临界区,再由系统随机挑选一个进程进行down操作。
5. 互斥量:
      (1)互斥量的使用:
         互斥量是一种简化的信号量,它是一个只能处于两态之一的变量(如0和1),只能进行加锁和解锁。
                 mutex_lock(&mutex)为加锁函数,当mutex为0时可以加锁,防止其他进程进入临界区;当mutex为1时,说明已经有进程在临界区,此时进程阻塞,调用pthread_yield让出CPU的占有权。
                 mutex_unlock(&mutex)为解锁函数,令mutex从1变为0,表示允许其他进程访问临界区,再有内核随机选择一个进程进入临界区。
      (2)互斥和同步的区别和联系:
               区别:多个进程同时访问临界区时,任一时刻只能有一个进程在访问临界区,其他进程等待该进程访问结束后再进行访问。互斥的原则是随机挑选一个进程进入临界区(无序访问),同步的原则是多进程对临界区的访问是有特定先后顺序(有序访问)。
               联系:同步是更复杂的互斥,而互斥则是特殊的同步。
       (3)与互斥量有关的ptread调用:
          pthread_mutex_init      创建一个互斥量
          pthread_mutex_destory    撤销一个已存在的互斥量
          pthread_mutex_lock       获得一个锁或者阻塞
          pthread_mutex_trylock     获得一个锁或者失败
          pthread_mutex_unlock     释放一个锁
6. 条件量:
     (1) 条件量的作用:
                条件量也是一种同步机制,允许线程由于一些未达到的条件而阻塞。
     (2) 条件量的使用:  
               条件量通常和互斥量一起使用,这种模式会先让一个线程锁住一个互斥量,然后判断它不能满足期待的条件时阻塞该线程,等待一个条件量唤醒,同时将该互斥量解锁。另一个线程向它发出条件量唤醒信号,使它继续进行。
                pthread_cond_wait(&条件量, &互斥量),表示:解锁互斥量,并阻塞调用线程,等待条件量唤醒。
                pthread_cond_signal(&条件量),表示:唤醒该条件量。
             (ps:原子性是指一个线程一旦开始执行,就必须执行结束,中间不能被切到另一个线程)         
    (2)与条件量有关的pthread调用:
          pthread_cond_init      创建一个条件变量
          pthread_cond_destory    撤销一个条件变量
          pthread_cond_wait       阻塞以等待一个信号
          pthread_cond_signal      向另一个线程发信号唤醒它
          pthread_cond_broadcast       向多个线程发信号让它们全部唤醒
7. 用户态和内核态:
           用户态:只能访问非外围设备的某些受限内存,不能控制CPU对进程切换。
           内核态:可以访问内存的所有数据,包括外围设备(硬盘、网卡、键盘),可以控制CPU进行进程切换。  
           用户态到内核态的切换:所有的用户程序都运行在用户态,当需要从硬盘读数据或者从键盘获取输入等外围设备的操作时,需要用用户态转成内核态,但是不能控制内核态中的指令,这种机制叫系统调用(或是陷阱调用)。大致流程是:
                        1. 用户态将信息装入寄存器,表明需要内核提供服务,随后执行系统调用请求
                        2. CPU切换到内核态,读取寄存器中的数值参数,完成相应的服务
                        3. 服务完成后,CPU重置回用户态,并返回结果
                    
 
原文地址:https://www.cnblogs.com/ladawn/p/8242390.html