关于信号量的静态、动态申明问题。大侠路过请进!

超低空MC 2014-11-30 08:49:21
各位大侠,再看LDD3的过程中会看到自旋锁、信号量等等变量的申明会有两种方式:


1、静态方式:DECLARE_MUTEX();
2、动态方式:void init_MUTEX();

我的理解是:第一种是用宏,第二种是用函数。为什么说第二种可以在运行时使用,宏就不行吗? 一直很疑惑,希望各位大侠路过可以给我解答一下。


不甚感激!
...全文
353 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
超低空MC 2014-12-02
  • 打赏
  • 举报
回复
引用 7 楼 micropentium6 的回复:
oops, both of them passed through!
Your wonderful answer make me understand a lot , thank you !
  • 打赏
  • 举报
回复
oops, both of them passed through!
  • 打赏
  • 举报
回复
引用 2 楼 MC_hust 的回复:
Thanks for your answer. Through your analysis. That is to say, the 2 methods have no difference in usage?
fucking csdn thought I am a web crawler! Screw u, Fucking CSDN!!! fact always speaks louder, let's explore the source a bit. Here is a version (2.6.31) of the implementation of semaphore

#ifndef __LINUX_SEMAPHORE_H
#define __LINUX_SEMAPHORE_H

 #include <linux/list.h>
#include <linux/spinlock.h>

 /* Please don't access any members of this structure directly */
struct semaphore {
         spinlock_t              lock;
         unsigned int            count;
         struct list_head        wait_list;
};

 #define __SEMAPHORE_INITIALIZER(name, n)                                \
 {                                                                       \
         .lock           = __SPIN_LOCK_UNLOCKED((name).lock),            \
        .count          = n,                                            \
         .wait_list      = LIST_HEAD_INIT((name).wait_list),             \
}

#define DECLARE_MUTEX(name)     \
         struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
 
static inline void sema_init(struct semaphore *sem, int val)
 {
         static struct lock_class_key __key;
         *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
        lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
}

 #define init_MUTEX(sem)         sema_init(sem, 1)
#define init_MUTEX_LOCKED(sem)  sema_init(sem, 0)
u can tell both DECLARE_MUTEX and init_MUTEX are defined as macros, which is different than LDD3's description, probably because LDD3 was published in 2005. And you can also tell both of them eventually requires __SEMAPHORE_INITIALIZER to initialize the semaphore variable. Even the function sema_init is declared as "inline", which basically tells the compiler: don't make me as a function if you don't have to... so, I would say there is no difference at all. You may think there is a subtle difference: by calling init_MUTEX, you could though, manipulate the variable before or afterward since it's defined in your source. However, DECLARE_MUTEX allows you to do the same thing, but it's vague, since no declaration can be found in your source for this variable...
  • 打赏
  • 举报
回复
引用 3 楼 MC_hust 的回复:
[quote=引用 1 楼 micropentium6 的回复:] don't know the detail, but generally speaking, macro is processed by pre-processor during the compilation. Basically, macro referred in the source code will be replaced by (expanded to) its definition before any real "compiling" starts. Therefore, if you do a symbol lookup on the obj file, you will not be able to find it. function, on the other hand, will have its instructions preserved in the executable in the .text section. In this context, you can say that function call can be invoked at the run time. For your case, by putting DECLARE_MUTEX (assuming it's a macro), a mutex will be defined/initialized in .data section; by adding init_MUTEX() in your logic, the mutex will be created only when this function is invoked. just my 2cents...
Thanks for your answer. Through your analysis. That is to say, the 2 methods have no difference in usage? [/quote] well, I guess fact always speaks louder, huh?

struct semaphore {
         spinlock_t              lock;
         unsigned int            count;
          struct list_head        wait_list;
 };
 
#define __SEMAPHORE_INITIALIZER(name, n)                                \
 {                                                                       \
         .lock           = __SPIN_LOCK_UNLOCKED((name).lock),            \
          .count          = n,                                            \
         .wait_list      = LIST_HEAD_INIT((name).wait_list),             \
 }
 
#define DECLARE_MUTEX(name)     \
        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
 
 static inline void sema_init(struct semaphore *sem, int val)
 {
        static struct lock_class_key __key;
         *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
          lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
 }

#define init_MUTEX(sem)         sema_init(sem, 1)
#define init_MUTEX_LOCKED(sem)  sema_init(sem, 0)
in this version (kernel 2.6.31.13 ) of the implementation of semaphore, both DECLARE_MUTEX and init_MUTEX are actually macros and both of them refers the same macro "__SEMAPHORE_INITIALIZER" to initialize the semaphore variable. sema_init. as the function expanded by init_MUTEX is declared as inline, which basically tells the compiler: don't make me as a function call if you could... there is actually not much difference at all. One subtle difference though, is, by init_MUTEX, you could manipulate the semaphore variable by your own, since you define it and send its address to init_MUTEX for initialization. With DECLARE_MUTEX, you could do the same, but it's vague, since the reader can't find the declaration of this variable...
LouisScola 2014-12-01
  • 打赏
  • 举报
回复
字面意思就可以理解,静态方式是指在编译时就为mutex信号量分配了内存空间,应该是在data/bss段,动态方式是在程序运行时才分配的,应该是放在heap段,这样可以节省内存空间,不需要这个mutex时也可以free掉
超低空MC 2014-12-01
  • 打赏
  • 举报
回复
引用 1 楼 micropentium6 的回复:
don't know the detail, but generally speaking, macro is processed by pre-processor during the compilation. Basically, macro referred in the source code will be replaced by (expanded to) its definition before any real "compiling" starts. Therefore, if you do a symbol lookup on the obj file, you will not be able to find it. function, on the other hand, will have its instructions preserved in the executable in the .text section. In this context, you can say that function call can be invoked at the run time. For your case, by putting DECLARE_MUTEX (assuming it's a macro), a mutex will be defined/initialized in .data section; by adding init_MUTEX() in your logic, the mutex will be created only when this function is invoked. just my 2cents...
Thanks for your answer. Through your analysis. That is to say, the 2 methods have no difference in usage?
超低空MC 2014-12-01
  • 打赏
  • 举报
回复
Thanks for your answer. Through your analysis. That is to say, the 2 methods have no difference in usage?
超低空MC 2014-12-01
  • 打赏
  • 举报
回复
引用 4 楼 LouisScola 的回复:
字面意思就可以理解,静态方式是指在编译时就为mutex信号量分配了内存空间,应该是在data/bss段,动态方式是在程序运行时才分配的,应该是放在heap段,这样可以节省内存空间,不需要这个mutex时也可以free掉
但是用DECLARE_MUTEX()宏来定义一个信号量也可以放在代码里面,然后用if判断是否需要申明,那就和用函数申明没差别了吧?
  • 打赏
  • 举报
回复
don't know the detail, but generally speaking, macro is processed by pre-processor during the compilation. Basically, macro referred in the source code will be replaced by (expanded to) its definition before any real "compiling" starts. Therefore, if you do a symbol lookup on the obj file, you will not be able to find it. function, on the other hand, will have its instructions preserved in the executable in the .text section. In this context, you can say that function call can be invoked at the run time. For your case, by putting DECLARE_MUTEX (assuming it's a macro), a mutex will be defined/initialized in .data section; by adding init_MUTEX() in your logic, the mutex will be created only when this function is invoked. just my 2cents...
Re:计算机网络 静态路由和动态路由协议 ======================# IP路由-网络层实现的功能:      网络畅通的条件      静态路由      路由汇总      默认路由      Windows上的路由表和默认路由      什么是动态路由      RIP协议和OSPF协议 # 网络层的功能:      只负责为数据包选择转发路径,不负责可靠传输和顺序到达 # 传输层的功能:      负责可靠传输或不可靠传输,且数据包到达后的排序 # RIP 协议 生产场景与工作原理:      静态路由存在的问题,例如有两条路径可以到达目的地,静态只配置一条路由,当出现故障的时候,路由器无法自动切换到新的链路中,因为是静态手工配置的路由!另外:如果网络环境大,采取了路由汇总或默认路由方式都难易应付量大且变化多的路由表时...! # OSPF 协议 生产场景与工作原理:      RIP协议是距离矢量协议,通过RIP协议路由器可以学习到所有网段距离以及下一跳给哪个路由器,但却不知道全网的拓扑结构(只有到了下一跳路由器,才能知道再下一跳怎样走)。RIP协议最大跳数15跳,因此不适合大规模网络。      OSPF ( Open Shortest Path First)协议是开放式最短路径优先协议,该协议是链路状态协议。OSPF协议通过路由器之间通告链路的状态来建立链路状态数据库,网络中所有路由器具有相同的链路状态数据库(所以需要划分区域,否则数据量太大了...),通过链路状态数据库就能构建出网络拓扑(即哪个路由器连接哪个路由器,以及连接的开销,带宽越高开销越低),运行OSPF协议的路由器通过网络拓扑计算到各个网络的最短路径(即开销最小的路径),路由器使用这些最短路径来构造路由表。 # 习题详解:静态路由和动态路由-----------------------------------------      

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧