免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 10413 | 回复: 17
打印 上一主题 下一主题

lock是如何实现的? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-10-09 17:52 |只看该作者 |倒序浏览
我们在应用程序中可以方便的使用系统提供的lock,但操作系统自己是如何实现这个lock的呢?

论坛徽章:
0
2 [报告]
发表于 2007-10-09 17:57 |只看该作者
加锁
while (lock condition is true)
    sleep()
set lock condition true

释放
set lock condition false
wakeup process sleeping on the condition

论坛徽章:
0
3 [报告]
发表于 2007-10-09 18:01 |只看该作者
有些就是汇编指令. 建议看看<深入理解Linux内核>的关于锁那章内容. 有非常详细的讲解.

论坛徽章:
0
4 [报告]
发表于 2007-10-09 18:06 |只看该作者

回复 #3 scutan 的帖子

正在看

论坛徽章:
0
5 [报告]
发表于 2007-10-09 18:30 |只看该作者
原帖由 空灵静世 于 2007-10-9 17:52 发表
我们在应用程序中可以方便的使用系统提供的lock,但操作系统自己是如何实现这个lock的呢?

我还以为lz要问锁在总线上是怎么实现的哦。
操作系统里面的就比较简单了,主要就信号量和自旋锁两种方式,说白了都是在内存中设个标志,通过读写该标志来判断锁的状态,不同是读写标志的方式、以及申请不到锁后的行为而已。各种各样的锁名称可能不一样,但实现大多采用了信号量和自旋锁的原理。建议lz把这两种搞懂就行了。

论坛徽章:
0
6 [报告]
发表于 2007-10-10 02:24 |只看该作者
原帖由 scutan 于 2007-10-9 18:01 发表
有些就是汇编指令. 建议看看的关于锁那章内容. 有非常详细的讲解.


好书。。。。

论坛徽章:
0
7 [报告]
发表于 2007-10-10 05:41 |只看该作者
给你一个我的自旋锁实现,顺便请高人挑挑毛病,看看有啥问题没有


class FoundationAPI SpinLock : NonCopyable
{
private:
                enum { LOCK = 0x20, UNLOCK };

                typedef AtomicFunction AtomicF;
private:
                volatile size_t                        m_state;
public:
               

                class FoundationAPI ScopeLock
                {
                private:
                                SpinLock        &m_lock;
                public:
                                ScopeLock(SpinLock &lock);

                                ~ScopeLock();
                };
public:
                SpinLock();

                ~SpinLock();
private:
                void Lock();
               
                void UnLock();
};



SpinLock::ScopeLock::ScopeLock(SpinLock &lock) :m_lock(lock)
{
                m_lock.Lock();
}



SpinLock::ScopeLock::~ScopeLock()
{
                m_lock.UnLock();
}


SpinLock::SpinLock() : m_state(UNLOCK)
                {

                }

SpinLock::~SpinLock()
                {
                                assert(m_state == UNLOCK);
                }

void SpinLock::Lock()
{
                while(AtomicF::CompareExchange(&m_state, LOCK, UNLOCK) != UNLOCK)
                {
                                Thread::YieldThread();
                }
}

void SpinLock::UnLock()
{
                assert(m_state == LOCK);
                AtomicF::CompareExchange(&m_state, UNLOCK, LOCK);
}




F_NAKED size_t F_STDCALL AtomicFunction::CompareExchange(volatile size_t *dest, size_t val, size_t cmpval)
{
                if(ProcessorCount == 1)
                {
                                __asm{
                                                mov eax, [esp + 12];//cmpval;
                                                mov ecx, [esp + 8];//val;
                                                mov edx, [esp + 4];//dest;
                                                cmpxchg [edx], ecx;
                                                ret 12;                        //eax作为返回值;
                                }
                }else
                {
                                __asm{
                                                mov eax, [esp + 12];//cmpval;
                                                mov ecx, [esp + 8];//val;
                                                mov edx, [esp + 4];//dest;
                                                lock cmpxchg [edx], ecx;
                                                ret 12;                        //eax作为返回值;
                                }
                }

}

多核下面,核心是这个lock,锁总线,至于总线上怎么实现的估计也是有一套复杂的协议和算法。

当然了,我认为一般系统无法获得锁之后,进入内核态,系统会把当前线程挂起来,选另一个线程运行,而后当解锁之后,会搜索哪些线程正在获得锁,而后选一个,将其继续执行。

[ 本帖最后由 Solidus 于 2007-10-10 05:47 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2007-10-10 08:57 |只看该作者
关键在于原子操作,一般由cpu提供原子操作指令。

论坛徽章:
0
9 [报告]
发表于 2007-10-10 10:08 |只看该作者
原帖由 Solidus 于 2007-10-10 05:41 发表
给你一个我的自旋锁实现,顺便请高人挑挑毛病,看看有啥问题没有


class FoundationAPI SpinLock : NonCopyable
{
private:
                enum { LOCK = 0x20, UNLOCK };

                typedef AtomicFunction AtomicF;
pr ...

C++看不懂。spinlock的实现比较简单,linux下的实现就很清楚。
此外,用户态程序是没有理由使用spinlock的,因为spinlock属于忙等待,用户态程序不应采用这种无法睡眠的锁机制。
对于lock的总线实现,说清楚了很复杂,对于程序员来说,只需要简单的知道如下原理就可以了(这是对于intel的cpu来说的):
对于p6以前的架构,lock会锁住整个总线,这个时候除了锁总线的cpu外其它cpu都不能发起内存操作。p6架构以后,lock会首先锁住本cpu的cache line,然后监听总线(snoop),一旦发现其它cpu的内存操作和自己锁住的cache line冲突了,则立即锁住总线,这时其它cpu再也无法发起操作。
以上也就是原子操作的总线实现。

论坛徽章:
0
10 [报告]
发表于 2007-10-10 10:23 |只看该作者
原帖由 zx_wing 于 2007-10-10 10:08 发表

C++看不懂。spinlock的实现比较简单,linux下的实现就很清楚。
此外,用户态程序是没有理由使用spinlock的,因为spinlock属于忙等待,用户态程序不应采用这种无法睡眠的锁机制。
对于lock的总线实现,说清楚 ...


确实大部分的情况下用户态使用spinlock都是极其糟糕的,但是在某些情况下(例如某些资源的初始化),竞争状态时极其罕见的,但是它确实存在,所以所以我认为在此时用spinlock是行之有效的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP