内容简介:主要讲解了Linux各个独立进程间(或线程间)相互通信的机制(主要是System V机制),由于涉及到进程间资源共享,引入资源保护问题,也就是Linux的锁。

5.1 控制机制

首先通过一个竞态条件的例子引入需要对锁的需求,然后介绍了Linux系统锁控制机制:临界区。一种典型的使用临界区机制的锁方法:信号量。

5.2 内核锁机制

讲解了Linux内核态几种锁机制:

1.      原子操作:

atomic_t

2.      自旋锁:

spinlock_t

3.      信号量:

struct semaphore

4.      读写锁:

rwlock_t

API:write_lock、read_lock、read_trylock等;

5.      RCU:read-copy-update。该机制记录了指向共享数据结构的指针的所有使用者。在数据将要改变时(写操作),先创建一个副本,在副本中修改。在所有的读访问的使用者结束对旧副本的读取后,指针替换为指向新的、修改后副本的指针。

rcu_dereference、rcu_read_lock、rcu_read_unlock

6.      内存与优化屏障

主要是阻止编译器的指令重排吧。比如读屏障:保证屏障之后发出的任何读操作执行之前,屏障之前发出的所有读操作已经执行完成(就是说屏障之后读取的内容肯定是最新的);

mb、rmb、wmb、smp_mb

barrier

7.      大内核锁:已废弃;

8.      互斥量

1)      经典互斥量:struct mutex

2)      实时信号量:struct rt_mutex,支持优先级反转;

9.      近似的per-CPU计数器

思想:计数器的准确值存储在内存中某处,准确值所在内存位置之后是一个数组,每个数组项对应于系统中的一个CPU。如果某个特定于CPU的数组元素修改后的绝对值超过某个阈值,内核确保通过适当的锁机制修改计数器的准确值。

1.3  System V进程间通信(用户态)

1.      信号量

相关操作:semget、semop、semctl

2.      共享内存

3.      消息队列

此部分内容讲解比较基础,具体的内容可以参阅《UNIX网络通信—进程间通信》。笔者通过以下例程简单介绍信号量的用法。

ipcd.c文件:

#include <stdio.h>
#include <getopt.h>
#include <pthread.h>
#include "../../../PUBILIC/include/basetype.h"
#include "ipc_sem.h"#define IPC_THREAD_NUM  10
#define IPC_MAX_ADD_NUM  10000BOOL_T g_bIsHaveLock = BOOL_FALSE;
UINT g_uiTestUint = 0;
pthread_t g_astThreadID[IPC_THREAD_NUM];ULONG ipc_ParseParam(INT argc, CHAR **argv)
{ULONG ulRet = ERROR_SUCCESS;INT iOption = 0;while (-1 != (iOption = getopt(argc, argv, "l:"))){switch (iOption){case 'l':{g_bIsHaveLock = BOOL_TRUE;break;}default:{ulRet = ERROR_FAILED;break;}}}return ulRet;
}VOID *ipc_thread_Func(VOID *pParam)
{UINT uiIndex;pthread_t stSelf;stSelf = pthread_self();if (BOOL_TRUE  == g_bIsHaveLock){IPC_Sem_Down();}for (uiIndex = 0; uiIndex < IPC_MAX_ADD_NUM; uiIndex++){g_uiTestUint++;}/* 加完之后再打印值 */printf("This is thread(%lu): UINT(%u)\n", stSelf, g_uiTestUint);if (BOOL_TRUE  == g_bIsHaveLock){IPC_Sem_Up();}return NULL;
}
ULONG ipc_Init()
{ULONG ulRet = ERROR_SUCCESS;UINT uiIndex;ulRet = IPC_Sem_Init();if (ERROR_SUCCESS != ulRet){return ulRet;}/* 创建10个线程同时对全局变量进行操作 */for (uiIndex = 0; uiIndex < IPC_THREAD_NUM; uiIndex++){pthread_create(&g_astThreadID[uiIndex], NULL, ipc_thread_Func, NULL);}return ulRet;
}VOID ipc_Fini()
{UINT uiIndex;for (uiIndex = 0; uiIndex < IPC_THREAD_NUM; uiIndex++){pthread_join(g_astThreadID[uiIndex], NULL);}IPC_Sem_Fini();return;
}INT main(INT argc, CHAR **argv)
{ULONG ulRet = ERROR_SUCCESS;/* 解析参数 */ulRet = ipc_ParseParam(argc, argv);if (ERROR_SUCCESS != ERROR_SUCCESS){return -1;}ulRet = ipc_Init();if (ERROR_SUCCESS != ulRet){ipc_Fini();}ipc_Fini();return 0;
}

ipc_sem.c文件:

#include <stdio.h>
#include <sys/sem.h>
#include "../../../PUBILIC/include/basetype.h"
#include "ipc_sem.h"struct sembuf g_stopDown[1] = {0, -1, 0};
struct sembuf g_stopUp[1] = {0, 1, 0};
INT g_iSemId = -1;ULONG IPC_Sem_Init()
{INT iSemId = -1;INT iRet;ULONG ulRet = ERROR_FAILED;/* 首先打开信号量 */iSemId = semget(IPC_SEM_LEY, 0, IPC_CREAT | 0666);if (iSemId < 0){/* 打开失败再创建 */printf("Sem(%ld) does not exist, then create it.\n", IPC_SEM_LEY);iSemId = semget(IPC_SEM_LEY, 1, IPC_CREAT | 0666);if (iSemId < 0){printf("Create sem(%ld) failed.", IPC_SEM_LEY);return ERROR_FAILED;}}/* 设置信号量值 */iRet = semctl(iSemId, 0, SETVAL, 1);if (iRet == 0){g_iSemId = iSemId;ulRet = ERROR_SUCCESS;}return ulRet;
}VOID IPC_Sem_Up()
{semop(g_iSemId, &g_stopUp[0], 1);return;
}
VOID IPC_Sem_Down()
{semop(g_iSemId, &g_stopDown[0], 1);return;
}VOID IPC_Sem_Fini()
{/* 删除信号量 */if (g_iSemId > 0){semctl(g_iSemId, 0, IPC_RMID);}return;
}

程序讲解:

1)      Main函数进来先解析参数:是否有锁,解析参数用于设置全局变量g_bIsHaveLock;

2)      ipc_Init()函数中的IPC_Sem_Init()函数打开或创建了一个信号量。之后创建了10个线程同时对全局变量IPC_Sem_Init进行10000次++操作,如果没有竞态条件发生,最后的结果应该是10 * 10000 = 100000;

3)      线程函数进去后先判断有没有锁:有锁则进行down操作,获取信号量,这样就不受其他线程干扰;没锁则直接进行变量++操作;

4)      通过以不同的命令行参数启动进程,可以看到有锁和没锁情况下全局变量的值。

程序效果:

1)      无锁启动

2)      有锁启动

补充说明:

1.      程序代码没贴全,如UINT、ULONG等类型申明都放在我的basetype.h头文件中,由于经常用到,所以用一个单独的头文件申明;

2.      Ipc_sem.h头文件没有贴,也就是一些函数申明;

总之:

读者应该理解信号量的精髓和使用方法,而不是简单的“抄”代码。

1.4  其他IPC机制

1.      信号

2.      管道和套接字

说明:此部分内容介绍更加简洁,实际上内容很多,读者需要在学习或工作中慢慢体会。

深入linux内核架构--第五章 锁与进程间通信相关推荐

  1. Linux内核分析——第五章 系统调用

    第五章 系统调用 5.1 与内核通信 1.系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: (1)为用户空间提供了一种硬件的抽象接口 (2)系统调用保证了系统的稳定和安全 ( ...

  2. Linux内核探讨-- 第五章

    本文是个人分析<Linux内核设计与实现>而写的总结,欢迎转载,请注明出处: http://blog.csdn.net/dlutbrucezhang/article/details/123 ...

  3. 深入Linux内核架构 (图灵程序设计丛书·LinuxUNIX系列)

    深入Linux内核架构 (图灵程序设计丛书·LinuxUNIX系列) 下载地址 https://pan.baidu.com/s/1SydaciM3sUkxN9JUbdttKw 扫码下面二维码关注公众号 ...

  4. linux内核测试指南 第一章

    linux内核测试指南 第一章 内核,补丁,内核树 和 编译 1.1 内核 Linux内核的当前版本通常可以从linux内核档案网站(http://www.kernel.org/)以一个大的压缩文件的 ...

  5. 搭建《深入Linux内核架构》的Linux环境

    搭建<深入Linux内核架构>的Linux环境 阅读目录(Content) 作者 软件 概述 正文 一.安装GCC 二.编译Linux内核 三.制作跟文件系统 四.运行qemu 五.启动l ...

  6. 一文看懂Linux内核!Linux内核架构和工作原理详解

    linux内核相关视频解析: 5个方面分析linux内核架构,让你对内核不再陌生 90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc的原理 手把手带你实现一个Linux内核 ...

  7. Linux内核学习(五):linux kernel源码结构以及makefile分析

    Linux内核学习(五):linux kernel源码结构以及makefile分析 前面我们知道了linux内核镜像的生成.加载以及加载工具uboot. 这里我们来看看linux内核的源码的宏观东西, ...

  8. 【Linux 内核 内存管理】内存管理架构 ① ( 内存管理架构组成 | 用户空间 | 内核空间 | MMU 硬件 | Linux 内核架构层次 | Linux 系统调用接口 )

    文章目录 一.内存管理架构组成 ( 用户空间 | 内核空间 | MMU 硬件 ) 二.Linux 内核架构层次 三.Linux 系统调用接口 一.内存管理架构组成 ( 用户空间 | 内核空间 | MM ...

  9. linux 两个驱动 竞争,Linux设备驱动第五章(并发和竞争)读书笔记(国外英文资料).doc...

    Linux设备驱动第五章(并发和竞争)读书笔记(国外英文资料) Linux设备驱动第五章(并发和竞争)读书笔记(国外英文资料) The fifth chapter is concurrency and ...

最新文章

  1. python 3下对stm32串口数据做解析
  2. python实现yolo目标检测_Yolov5—实现目标检测(win10)
  3. 深度学习不能取代计算机视觉技术背后的真正原因
  4. 5获取http请求头_获取托管者发送http请求报文的解决方案
  5. 【深度学习】Ivy 开源框架,深度学习大一统时代到来?
  6. 沉默是金 矩阵快速幂
  7. Angular 条件指令 ngIf 的一个例子
  8. JavaScript之event事件
  9. java匿名类和匿名对象及this的其他用法
  10. Spark Streaming之运行原理
  11. stata 倾向得分匹配(二)偏差校正匹配估计量
  12. 三元组相加获得target
  13. moosefs即将发布新版
  14. can硬件结构和工作原理_汽车CAN总线工作原理及测量方法详解
  15. HIVE存储(五)HIVE文件的性能测试
  16. MySQL 有这一篇就够(呕心狂敲37k字,只为博君一点赞!!!)
  17. APIO2019 打铁记
  18. 关于适配器网络出现/键盘注册表损坏
  19. 将ttc改为otf_Font Renamer字体更名、重命名工具_支持ttf、ttc、otf、pfb字体 V3.0 下载...
  20. 计算几何入门 1.3:凸包的构造——增量构造法

热门文章

  1. android 手机误删短信恢复软件,误删除短信恢复大师 for android v4.1 安卓版 恢复Android手机上误删除的短信记录的软件...
  2. 在一起计时器_设计作品|最佳倒数计时器设计分析「附原型实例」
  3. 频繁跳槽的人简历是不是更容易被淘汰?
  4. Implement int sqrt(int x).
  5. 分析师入门常见错误 幸存者偏差,如何用匹配和加权法规避
  6. 视频回顾|Pulsar Summit Asia 2021,案例、运维、生态干货不断
  7. 牛逼了啊!用 JS 实现了识别网页验证码的功能!
  8. bash忽略错误继续执行_shell 执行命令失败则中断执行 类似断言
  9. 【游戏建模全流程】ZBrush生物模型雕刻教程:豹纹壁虎
  10. 计算机专业综合素质试题答案,2015中学教师资格证考试试题及答案《综合素质》(4)...