linux环形缓冲区区为什么是lock-free的

用户名:UltraSQL
文章数:485
评论数:242
访问量:857039
注册日期:
阅读量:1297
阅读量:3317
阅读量:586300
阅读量:472406
51CTO推荐博文
SQL Server 环形缓冲区(Ring Buffer) -- RING_BUFFER_EXCEPTION 跟踪异常动态管理视图sys.dm_os_ring_buffers使得实时定位问题更加容易。环形缓冲包含大量的在服务器上发生的事件。当前,我正碰到锁请求超时问题。根据SQL Server Profiler跟踪捕获,发现服务器收到大量如下信息:&Lock request time out period exceeded.&我们找到了语句并修改,来阻止所请求超时的发生。现在服务器正被监控,我不想运行SQL Server Profiler去跟踪这个消息的产生。所以,我想用环形缓冲动态管理视图去监控是否服务器上有进一步的锁请求超时发生。这使得监控实例更容易。&下面的脚本给出了一个存储在环形缓冲区中的异常的时间范围,输出了大量的发生的异常。&对于SQL Server 2005:&DECLARE&@ts_now&BIGINT,@dt_max&BIGINT,&@dt_min&BIGINT
SELECT&@ts_now&=&cpu_ticks&/&CONVERT(FLOAT,&cpu_ticks_in_ms)&FROM&sys.dm_os_sys_info
select&@dt_max&=&MAX(timestamp),&@dt_min&=&MIN(timestamp)&from&sys.dm_os_ring_buffers&WHERE&ring_buffer_type&=&N'RING_BUFFER_EXCEPTION'
select&DATEADD(ms,&-1&*&(@ts_now&-&@dt_max),&GETDATE())&AS&MaxTime,
DATEADD(ms,&-1&*&(@ts_now&-&@dt_min),&GETDATE())&AS&MinTime
SELECT&record_id,
DATEADD(ms,&-1&*&(@ts_now&-&[timestamp]),&GETDATE())&AS&EventTime,y.Error,UserDefined,b.description&as&NormalizedText
record.value('(./Record/@id)[1]',&'int')&AS&record_id,
record.value('(./Record/Exception/Error)[1]',&'int')&AS&Error,
record.value('(./Record/Exception/UserDefined)[1]',&'int')&AS&UserDefined,TIMESTAMP
SELECT&TIMESTAMP,&CONVERT(XML,&record)&AS&record
FROM&sys.dm_os_ring_buffers
WHERE&ring_buffer_type&=&N'RING_BUFFER_EXCEPTION'
AND&record&LIKE&'%&%')&AS&x)&AS&y
INNER&JOIN&sys.sysmessages&b
on&y.Error&=&b.error
WHERE&b.msglangid&=&1033&and&y.Error&=&1222&--&Change&the&message&number&to&the&message&number&that&you&want&to&monitor
ORDER&BY&record_id&DESC&对于SQL Server 2008:&DECLARE&@ts_now&BIGINT,@dt_max&BIGINT,&@dt_min&BIGINT
SELECT&@ts_now&=&cpu_ticks/(cpu_ticks/ms_ticks)&FROM&sys.dm_os_sys_info
select&@dt_max&=&MAX(timestamp),&@dt_min&=&MIN(timestamp)&from&sys.dm_os_ring_buffers&WHERE&ring_buffer_type&=&N'RING_BUFFER_EXCEPTION'
select&DATEADD(ms,&-1&*&(@ts_now&-&@dt_max),&GETDATE())&AS&MaxTime,
DATEADD(ms,&-1&*&(@ts_now&-&@dt_min),&GETDATE())&AS&MinTime
SELECT&record_id,
DATEADD(ms,&-1&*&(@ts_now&-&[timestamp]),&GETDATE())&AS&EventTime,Error,UserDefined,text&as&NormalizedText
record.value('(./Record/@id)[1]',&'int')&AS&record_id,
record.value('(./Record/Exception/Error)[1]',&'int')&AS&Error,
record.value('(./Record/Exception/UserDefined)[1]',&'int')&AS&UserDefined,TIMESTAMP
SELECT&TIMESTAMP,&CONVERT(XML,&record)&AS&record
FROM&sys.dm_os_ring_buffers
WHERE&ring_buffer_type&=&N'RING_BUFFER_EXCEPTION'
AND&record&LIKE&'%&%')&AS&x)&AS&y
INNER&JOIN&sys.messages&b
on&y.Error&=&b.message_id
WHERE&b.language_id&=&1033&and&y.Error&=&1222&--&Change&the&message&number&to&the&message&number&that&you&want&to&monitor
ORDER&BY&record_id&DESC&&本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)
本文收录至博客专题:《》自定义print函数缓存打印数据到环形缓冲区
> 自定义print函数缓存打印数据到环形缓冲区
自定义print函数缓存打印数据到环形缓冲区
驱动程序:#include "linux/module.h"#include "linux/kernel.h"#include "linux/fs.h"#include "linux/init.h"#include "linux/delay.h"#include "asm/uaccess.h"#include "asm/irq.h""#include "asm/io.h"#include "asm/arch/regs-gpio.h"#include ""asm/hardware.h"#include "linux/proc_fs.h"#define MYLOG_BUF_LEN 1024struct proc_dir_entry *static char mylog_buf[MYLOG_BUF_LEN];static char tmp_buf[MYLOG_BUF_LEN];static int mylog_r = 0;static int mylog_r_for_read = 0;static int mylog_w = 0;static DECLARE_WAIT_QUEUE_HEAD(mymsg_waitq);static int is_mylog_empty(void){
return (mylog_r == mylog_w);}static int is_mylog_empty_for_read(void){
return (mylog_r_for_read == mylog_w);}static int is_mylog_full(void){
return ((mylog_w + 1)% MYLOG_BUF_LEN == mylog_r);}static void mylog_putc(char c){
if (is_mylog_full())
// 丢弃一个数据 //
mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
if ((mylog_r_for_read + 1) % MYLOG_BUF_LEN == mylog_r)
mylog_r_for_read = mylog_r;
mylog_buf[mylog_w] =
mylog_w = (mylog_w + 1) % MYLOG_BUF_LEN;
// 唤醒等待数据的进程 //
wake_up_interruptible(&mymsg_waitq);
// 唤醒休眠的进程 //}static int mylog_getc(char *p){
if (is_mylog_empty())
*p = mylog_buf[mylog_r];
mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
return 1;}static int mylog_getc_for_read(char *p){
if (is_mylog_empty_for_read())
*p = mylog_buf[mylog_r_for_read];
mylog_r_for_read = (mylog_r_for_read + 1) % MYLOG_BUF_LEN;
return 1;}int myprintk(const char *fmt, ...){
va_start(args, fmt);
i = vsnprintf(tmp_buf, INT_MAX, fmt, args);
va_end(args);
for (j = 0; j < j++)
mylog_putc(tmp_buf[j]);
}static ssize_t mymsg_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos){
int error = 0;
int i = 0;
// 把mylog_buf的数据copy_to_user, return //
if ((file->f_flags & O_NONBLOCK) && is_mylog_empty_for_read())
return -EAGAIN;
//printk("%s %d\n", __FUNCTION__, __LINE__);
//printk("count = %d\n", count);
//printk("mylog_r = %d\n", mylog_r);
//printk("mylog_w = %d\n", mylog_w);
error = wait_event_interruptible(mymsg_waitq, !is_mylog_empty_for_read());
//printk("%s %d\n", __FUNCTION__, __LINE__);
//printk("count = %d\n", count);
//printk("mylog_r = %d\n", mylog_r);
//printk("mylog_w = %d\n", mylog_w);
while (!error && (mylog_getc_for_read(&c)) && i < count) {
error = __put_user(c, buf);
if (!error)
}static int mymsg_open(struct inode *inode, struct file *file){
mylog_r_for_read = mylog_r;
return 0;}const struct file_operations proc_mymsg_operations = {
.open = mymsg_open,
.read = mymsg_read,};static int mymsg_init(void){
myentry = create_proc_entry("mymsg", S_IRUSR, &proc_root);
if (myentry)
myentry->proc_fops = &proc_mymsg_
return 0;}static void mymsg_exit(void){
remove_proc_entry("mymsg", &proc_root);}module_init(mymsg_init);module_exit(mymsg_exit);EXPORT_SYMBOL(myprintk);MODULE_LICENSE("GPL");===============================================================解析:当其他驱动程序调用自定义的myprintk函数打印数据时不会立即把数据打印在前台显示,而是把数据放在mylog_buf环形缓冲区中保存,当应用程序查看proc/mymsg时,即执行:cat /proc/mymsg时会调用mymsg_read函数读取环型缓冲区,如果缓冲区中有数据会调用__put_user返回,如果没有数据系统会休眠。
分享给小伙伴们:
我来说两句……
最新技术贴
微信公众号二
微信公众号一|版面-Linux 开发与高级讨论(LinuxDev)主题:环形缓冲区,一个读线程一个写线程,需要互斥么?一个环形缓冲区,维护两个指针,读指针和写指针,读线程每次读取一段长度数据,写线程每次写一段长度数据。不知道需不需要在访问和更新读写指针的时候加锁。&&我想的是,比如读线程读之前判断一下有没有足够数据,如果有,就读取,读完后再更新读指针,写线程类似。那么不管读线程读到的写指针是写线程更新前的还是更新后的,都不会有逻辑问题,实在想不出有什么情况有竞争?&&我对多线程竞争现象的理解很浅,盼望高人能够指教一下。--FROM 219.234.81.*对于读写指针可以使用atomic_t,能保证移动指针时候的原子性,而且不用mutex【 在 kingjerry (hhh) 的大作中提到: 】: 标&&题: 环形缓冲区,一个读线程一个写线程,需要互斥么?: 发信站: 水木社区 (Fri May 14 23:25:19 2010), 站内: : 一个环形缓冲区,维护两个指针,读指针和写指针,读线程每次读取一段长度数据,: 写线程每次写一段长度数据。不知道需不需要在访问和更新读写指针的时候加锁。: :&& 我想的是,比如读线程读之前判断一下有没有足够数据,如果有,就读取,读完后再更: 新读指针,写线程类似。那么不管读线程读到的写指针是写线程更新前的还是更新后的,: 都不会有逻辑问题,实在想不出有什么情况有竞争?:&& 我对多线程竞争现象的理解很浅,盼望高人能够指教一下。: --: : ※ 来源:·水木社区 ·[FROM: 219.234.81.*]--FROM 114.246.84.*最简单的,2个reader怎么办?复杂点的编译器和CPU都可能打乱你预期的内存操作顺序,Reader可能先见到指针的移动,然后Writer的数据才真真进到buffer【 在 kingjerry (hhh) 的大作中提到: 】: 一个环形缓冲区,维护两个指针,读指针和写指针,读线程每次读取一段长度数据,: 写线程每次写一段长度数据。不知道需不需要在访问和更新读写指针的时候加锁。:&& 我想的是,比如读线程读之前判断一下有没有足够数据,如果有,就读取,读完后再更: ...................--FROM 123.112.83.*关键是你如何判断缓冲区是否有数据和缓冲区是否满。一般情况下是同时需要这两个指针的,这就可能datarace了【 在 kingjerry (hhh) 的大作中提到: 】: 一个环形缓冲区,维护两个指针,读指针和写指针,读线程每次读取一段长度数据,: 写线程每次写一段长度数据。不知道需不需要在访问和更新读写指针的时候加锁。:&& 我想的是,比如读线程读之前判断一下有没有足够数据,如果有,就读取,读完后再更: ...................--FROM 221.223.42.*这个用pipe不是少了这些麻烦了么【 在 kingjerry (hhh) 的大作中提到: 】: 一个环形缓冲区,维护两个指针,读指针和写指针,读线程每次读取一段长度数据,: 写线程每次写一段长度数据。不知道需不需要在访问和更新读写指针的时候加锁。:&& 我想的是,比如读线程读之前判断一下有没有足够数据,如果有,就读取,读完后再更: ...................--FROM 222.130.190.*【 在 kingjerry (hhh) 的大作中提到: 】: 一个环形缓冲区,维护两个指针,读指针和写指针,读线程每次读取一段长度数据,: 写线程每次写一段长度数据。不知道需不需要在访问和更新读写指针的时候加锁。:&& 我想的是,比如读线程读之前判断一下有没有足够数据,如果有,就读取,读完后再J. Giacomoni, T. Moseley, and M. Vachharajani. FastForward for Efficient Pipeline Parallelism - A Cache-OptimizedConcurrent Lock-Free Queue. PPoPP 2008.--修改:ilovecpp FROM 222.129.41.*FROM 222.129.41.*很典型的一个lock-free设计我06年左右第一次用了一个这样的东西。好来才知道公司已经很多人在用这样的设计了【 在 kingjerry (hhh) 的大作中提到: 】: 一个环形缓冲区,维护两个指针,读指针和写指针,读线程每次读取一段长度数据,: 写线程每次写一段长度数据。不知道需不需要在访问和更新读写指针的时候加锁。:&& 我想的是,比如读线程读之前判断一下有没有足够数据,如果有,就读取,读完后再更: ...................--修改:cygwin FROM 211.157.100.*FROM 211.157.100.*两个reader肯定有问题,但是只有一个reader,一个writer呢如果我保证都是在读取(写入)数据以后,再移动读写指针呢。因为我每次都是读写一段数据,读写前我先判断是否有那么长的数据可以操作,操作后,再去更新指针,会有问题么?另外所谓的编译器和CPU打乱内存操作顺序,是指我假设的操作以后再更新指针,不被保证么?【 在 kirbyzhou (下雪 你那边下雪了么?) 的大作中提到: 】: 最简单的,2个reader怎么办?: 复杂点的: 编译器和CPU都可能打乱你预期的内存操作顺序,: ...................--FROM 219.234.81.*pipe的效率能够保证么,我这个缓冲想用在千兆网口,速率要求很高,不知道能不能满足【 在 e890ac39a3de (Sold) 的大作中提到: 】: 这个用pipe不是少了这些麻烦了么--FROM 219.234.81.*感觉“读写数据”和“给指针赋值”这两步有可能会乱序执行【 在 kingjerry (hhh) 的大作中提到: 】: 两个reader肯定有问题,但是只有一个reader,一个writer呢: 如果我保证都是在读取(写入)数据以后,再移动读写指针呢。: 因为我每次都是读写一段数据,读写前我先判断是否有那么长的: ...................--FROM 61.135.152.* 选择讨论区&BYR-Team2010. KBS Dev-Team2011&&}

我要回帖

更多关于 stm32串口环形缓冲区 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信