在我想办法弄懂supermirco 服务用的Super IO w83795的驱动的时候 ,我不幸又陷入了mutex_lock :
具体的设计文档见 document/mutex-design. 我这里只是摘录演义~
故事开始:
"为什么在这个地球上 ,我们需要一个新的mutex 子系统 ,
原来的semaphore怎了么他不行了吗 "
让我来帮大家怀恋一下他吧
struct semaphore {
spinlock_t lock;
unsigned int count;
struct list_head wait_list;
};
void down(struct semaphore *sem);//ldd上说 你是惹恼的用户的好方法
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);
void up(struct semaphore *sem);
其实,错不在semaphore . 而是我的心变了.
现在有一个简单的 mutex语义出现了,他完全满足我的代码需要, 而且semaphore 有下面的诱惑.
第一:
'struct mutex' 在大多数的平台上他更小 只有16字节 而你 'struct semaphore' 有20个字节
要知道更小的结构意味着 更少的 RAM空间 ,能更好的被CPU cache利用
第二:
紧凑的代码, 在x86上, .text的大小比较:
写道
text data bss dec hex filename
3280380 868188 396860 4545428 455b94 vmlinux-semaphore
3255329 865296 396732 4517357 44eded vmlinux-mutex
你看 25051字节的代码被节省了 小代码意味着更优越的指令高速缓冲存储器占用 ,这是linux 内核当前优化的主要目标
第三:
mutex 子系统 对于竞争带来的负载 表现的更轻盈更可扩展(想想长矛). 在一个8-way的 x86系统上,允许一个
基于mutex的内核测试 creat+unlink+close 在/tmp文件系统下 16个并行的任务:
写道
Semaphores: Mutexes:
$ ./test-mutex V 16 10 $ ./test-mutex V 16 10
8 CPUs, running 16 tasks. 8 CPUs, running 16 tasks.
checking VFS performance. checking VFS performance.
avg loops/sec: 34713 avg loops/sec: 84153
CPU utilization: 63% CPU utilization: 22%
结果显而易见 ~
第四:
没有快路径的开销(看下面) 只要2条汇编指令这和 semaphora是一样的
c0377ccb <mutex_lock>:
c0377ccb: f0 ff 08 lock decl (%eax)
c0377cce: 78 0e js c0377cde <.text.lock.mutex>
c0377cd0: c3 ret
不容忽视的好处:
struct mutex 被很好的赋义
* 一次只有一个任务可以拥有mutex
* 只有拥有者可以解锁
* 多次解锁是不允许的
* 递归加锁也是不可以的
* 一个mutex对象必须通过api初始化不能memset啥的
* 拥有mutex的任务不能exit
* 被锁控制的内存区域不能free
* mutex不能在软件中断或者硬件中断中
* 可以在tasklets软中断或者timers的context中
(ps 以上除了第3条当 mutexattr_init 为"PTHREAD_MUTEX_RECURSIVE_NP" 前几条大家其实和 pthread_mutex是一样一样的~)
当编译内核的 CONFIG_DEBUG_MUTEXES 打开后会变得更强大
* - uses symbolic names of mutexes, whenever they are printed in debug output
* - point-of-acquire tracking, symbolic lookup of function names
* - list of all locks held in the system, printout of them
* - owner tracking
* - detects self-recursing locks and prints out all relevant info
* - detects multi-task circular deadlocks and prints out all affected
* locks and tasks (and only those tasks)
--------------------------------------------------------------------------------
当然他也有一些缺点
你不能用在中断上下文 也不能在不同的context中解锁 但是semaphore可以
下面来简单看一些函数
void __sched mutex_lock(struct mutex *lock)
{
might_sleep();
/*
* The locking fastpath is the 1->0 transition from
* 'unlocked' into 'locked' state.
*/
__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
mutex_set_owner(lock);
}
这里有一个 might_sleep();
如果编译内核打开了 CONFIG_PREEMPT_VOLUNTARY 宏,那么在这里就如果需要就会面临 schedule();
__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
其实是把原子计数 conut 从1变成0 ,如果初始值不是1 ,那么这里就去调用 __mutex_lock_slowpath 函数
这样就进入了慢加锁的 路径(原来是不是很快呢,有的体系结构上是用汇编写的)
static __used noinline void __sched//__used gcc版本适应 __sched
__mutex_lock_slowpath(atomic_t *lock_count)
{
struct mutex *lock = container_of(lock_count, struct mutex, count);
__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, _RET_IP_);
}
首先container_of 获得对应原子数的 mutex,然后去调用不可中断的 __mutex_lock_common()
待续
分享到:
相关推荐
5. **线程编程**:多线程是现代程序设计的重要部分,Chap06的代码可能涵盖了线程的创建、同步和通信,如CreateThread、WaitForSingleObject和Mutex。 6. **GDI图形设备接口**:Chap07可能涉及Windows的GDI,讲解...
《宋宝华<Linux设备驱动>随书源代码》是一份宝贵的资料,它为学习Linux设备驱动开发提供了实践平台。Linux作为一个开源操作系统,其设备驱动程序是系统与硬件交互的关键,理解和编写设备驱动是深入掌握Linux系统的...
#include <windows.h> #include <iostream> #define BUFFER_SIZE 10 HANDLE mutex = CreateMutex(NULL, FALSE, NULL); // 创建互斥量 HANDLE semaphore = CreateSemaphore(NULL, BUFFER_SIZE, BUFFER_SIZE, NULL);...
5. **头文件和库**:了解如何包含Linux系统头文件,如`<unistd.h>`、`<stdlib.h>`、`<sys/types.h>`等,使用系统调用接口。掌握动态链接和静态链接库的区别,如`-l`选项链接库。 6. **进程与线程**:理解进程...
#include <pthread.h> pthread_t newThread; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_...
5. **C++11及以上版本的现代特性头文件**:如<tuple>(元组)、<unordered_map>(无序映射)、<mutex>(互斥锁)等,引入了更多高级特性。 此外,资源中还提到了其他技术领域如Python、GNU、ASM、Goom、Netatalk和...
- `<mutex>` 和 `<condition_variable>`:互斥锁和条件变量。 - `<shared_ptr>`,`<unique_ptr>` 和 `<weak_ptr>`:智能指针,自动管理内存。 - `<tuple>`:元组类型,存储多个不同类型的数据。 - `<forward_...
- **<assert.h>** - **功能**:提供了断言宏`assert()`,用于程序调试过程中检查假设条件是否成立。 - **示例**: ```c #include <assert.h> int main() { assert(2 + 2 == 4); return 0; } ``` - **...
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #define N 50000//设定计算次数 #define NUM 2//设定线程数,经过反复实验,在装有1个双核CPU的机器上,两个线程最快 double ...
8. `<pthread.h>`:多线程编程,提供了线程创建、同步、互斥锁等函数,如`pthread_create`、`pthread_join`、`pthread_mutex_lock`等。 9. `<dirent.h>`:目录操作,如`opendir`、`readdir`用于读取目录内容。 10....
9. 多线程:`<pthread.h>`提供了多线程编程接口,包括创建线程`pthread_create`,同步机制如互斥锁`pthread_mutex_lock`和条件变量`pthread_cond_wait`。 10. 队列和堆栈:`<queue.h>`和`<stack.h>`提供了队列和...
`<linux/kernel.h>`头文件提供了许多基本的内核功能,如日志记录(`printk`)、内存管理(`kmalloc`, `kfree`)、互斥锁(`mutex_lock`, `mutex_unlock`)等。这些功能对于驱动程序来说是非常基础且重要的。 ### 3. `...
<br>8.4.6 示例——图像浏览器<br>第9章 多线程编程<br>9.6.1 示例——使用全局变量通信<br>9.6.2 示例——使用Windows消息通信<br>9.7.5 示例——使用CriticalSection对象<br>9.7.7 示例——使用Mutex对象<br>9.7.9...
<br>8.4.6 示例——图像浏览器<br>第9章 多线程编程<br>9.6.1 示例——使用全局变量通信<br>9.6.2 示例——使用Windows消息通信<br>9.7.5 示例——使用CriticalSection对象<br>9.7.7 示例——使用Mutex对象<br>9.7.9...
- `<mutex>`和`<atomic>`:线程同步和原子操作。 - `<chrono>`:时间点和持续时间的处理,替代了`<ctime>`。 6. **头文件的包含规则** - 尽量避免循环包含,即一个头文件不应直接或间接包含自身。 - 使用`#...
std::unique_lock<std::mutex> lock(mutex_); tasks_.push(task); condition_.notify_one(); } std::function<void()> pop() { std::unique_lock<std::mutex> lock(mutex_); while (tasks_.empty()) { ...
9. **网络编程**:`<sys/socket.h>`和`<netinet/in.h>`等头文件提供了网络编程接口,如`socket`创建套接字,`bind`绑定地址,`listen`监听连接,`accept`接收连接,`send`和`recv`发送接收数据。 10. **国际化与...
9. **<pthread.h>**:多线程库,允许程序员创建和管理线程,如pthread_create、pthread_join和pthread_mutex_*系列函数用于线程创建、同步和互斥锁。 以上只是Linux C库函数的一小部分,实际上还有更多针对特定任务...
18. <mutex>、<lock> 等:互斥库,提供了线程同步机制的类和函数,如互斥锁、锁的使用等。 19. <memory>:内存管理库,提供了智能指针和内存分配函数,用于自动化内存管理。 20. <functional>:函数对象库,提供了...
`<pthread.h>`是用于处理POSIX线程(pthread)的头文件,`<stdio.h>`和`<string.h>`是标准输入输出和字符串处理函数,而`<sys/time.h>`则包含时间相关的函数。 定义常量`MAX`为10,表示每个线程将执行的循环次数。...