linux内核debug的一种方式:procfs
#include <linux/module.h> #include <linux/compat.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vt.h>
#include <linux/init.h>
#include <linux/linux_logo.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/kmod.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/efi.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/kthread.h>
#include <linux/poll.h> /*Proc based contron intertace*/
#define AUDIO_DEBUG_PROC_DIR "audio"
#define AUDIO_DEBUG_PROC_INFO "debuginfo"
#define MAX_BUF_WT_LEN 200 //do not bigger than one page size 1024 bytes
#define MAX_BUF_RD_LEN 2048 static struct proc_dir_entry *audio_proc_dir = NULL;
static struct proc_dir_entry *audio_proc_dbginfo_file = NULL; static struct deca_device *audio_deca_dev=NULL;
static struct snd_device *audio_snd_dev=NULL; static char *audio_info_buffer = NULL;
static __u32 g_dbg_show_en = ;
static __u32 g_dbg_show_interval = ;
static struct mutex audio_dbg_mutex;
wait_queue_head_t audio_dbg_wq;
static struct task_struct *audio_dbg_show_thread_ptr; static char *audio_state(unsigned long state)
{
char *ret = NULL;
switch(state)
{
case :
ret="DETACH";
break;
case :
ret="ATTACH";
break;
case :
ret="IDLE";
break;
case :
ret="PLAY";
break;
case :
ret="PAUSE";
break;
default:
ret="UNKNOWN";
break;
}
return ret;
}
static char *audio_sub_state(unsigned long state)
{
char *ret = NULL;
switch(state)
{
case :
ret="IDLE";
break;
case :
ret="NORMAL";
break;
case :
ret="NO DATA";
break;
case :
ret="NO BUFF";
break;
default:
ret="UNKNOWN";
break;
}
return ret;
}
static int audio_read_debug_info(char * buffer)
{
int len = ;
unsigned long len_max = MAX_BUF_RD_LEN - ;
struct audio_dbg_info dbg_info; if(!audio_deca_dev || !audio_snd_dev)
{
return -EUNATCH;
} if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))
{
len += sprintf(&buffer[len],"\ndesc enable : %s\n", (==dbg_info.snd.ad_en)?"yes":"no");
if (len_max <= len)
goto out; len += sprintf(&buffer[len],"deca state : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);
if (len_max <= len)
goto out; len += sprintf(&buffer[len],"deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);
if (len_max <= len)
goto out; len += sprintf(&buffer[len],"snd state : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);
if (len_max <= len)
goto out; len += sprintf(&buffer[len],"snd sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state);
if (len_max <= len)
goto out; len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
if (len_max <= len)
goto out;
len += sprintf(&buffer[len],"|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |\n");
if (len_max <= len)
goto out; /* deca buff info */
len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
if (len_max <= len)
goto out;
len += sprintf(&buffer[len],"|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
(int)((dbg_info.deca.prog_bs_buff_rm*)/(dbg_info.deca.prog_bs_buff_len)),
(unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,
(int)((dbg_info.deca.desc_bs_buff_rm*)/(dbg_info.deca.desc_bs_buff_len)),
(unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);
if (len_max <= len)
goto out;
len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
if (len_max <= len)
goto out;
len += sprintf(&buffer[len],"|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
(int)((dbg_info.deca.prog_cb_buff_rm*)/(dbg_info.deca.prog_cb_buff_len)),
(unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,
(int)((dbg_info.deca.desc_cb_buff_rm*)/(dbg_info.deca.desc_cb_buff_len)),
(unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len);
if (len_max <= len)
goto out; /* snd buff info */
len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
if (len_max <= len)
goto out;
len += sprintf(&buffer[len],"|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
(int)((dbg_info.snd.sync_buff_pcm_rm*)/(dbg_info.snd.sync_buff_pcm_len)),
(unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,
(int)((dbg_info.snd.sync_buff_desc_pcm_rm*)/(dbg_info.snd.sync_buff_desc_pcm_len)),
(unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,
(int)((dbg_info.snd.sync_buff_dd_rm*)/(dbg_info.snd.sync_buff_dd_len)),
(unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,
(int)((dbg_info.snd.sync_buff_ddp_rm*)/(dbg_info.snd.sync_buff_ddp_len)),
(unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len );
if (len_max <= len)
goto out;
len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
if (len_max <= len)
goto out;
len += sprintf(&buffer[len],"|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
(int)((dbg_info.snd.dma_buff_pcm_rm*)/(dbg_info.snd.dma_buff_pcm_len)),
(unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,
(int)((dbg_info.snd.dma_buff_dd_rm*)/(dbg_info.snd.dma_buff_dd_len)),
(unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,
(int)((dbg_info.snd.dma_buff_ddp_rm*)/(dbg_info.snd.dma_buff_ddp_len)),
(unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len );
if (len_max <= len)
goto out; len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n\n");
if (len_max <= len)
goto out;
} out:
return len;
} static int audio_show_debug_info(void)
{
struct audio_dbg_info dbg_info; if(!audio_deca_dev || !audio_snd_dev)
{
return -EUNATCH;
} if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))
{
printk( "\ndesc enable : %s\n", (==dbg_info.snd.ad_en)?"yes":"no");
printk( "deca state : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);
printk( "deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);
printk( "snd state : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);
printk( "snd sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state); printk( "+-----+------------------+------------------+------------------+------------------+\n");
printk( "|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |\n"); /* deca buff info */
printk( "+-----+------------------+------------------+------------------+------------------+\n");
printk( "|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
(int)((dbg_info.deca.prog_bs_buff_rm*)/(dbg_info.deca.prog_bs_buff_len)),
(unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,
(int)((dbg_info.deca.desc_bs_buff_rm*)/(dbg_info.deca.desc_bs_buff_len)),
(unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);
printk( "+-----+------------------+------------------+------------------+------------------+\n");
printk( "|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
(int)((dbg_info.deca.prog_cb_buff_rm*)/(dbg_info.deca.prog_cb_buff_len)),
(unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,
(int)((dbg_info.deca.desc_cb_buff_rm*)/(dbg_info.deca.desc_cb_buff_len)),
(unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len); /* snd buff info */
printk( "+-----+------------------+------------------+------------------+------------------+\n");
printk( "|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
(int)((dbg_info.snd.sync_buff_pcm_rm*)/(dbg_info.snd.sync_buff_pcm_len)),
(unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,
(int)((dbg_info.snd.sync_buff_desc_pcm_rm*)/(dbg_info.snd.sync_buff_desc_pcm_len)),
(unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,
(int)((dbg_info.snd.sync_buff_dd_rm*)/(dbg_info.snd.sync_buff_dd_len)),
(unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,
(int)((dbg_info.snd.sync_buff_ddp_rm*)/(dbg_info.snd.sync_buff_ddp_len)),
(unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len );
printk( "+-----+------------------+------------------+------------------+------------------+\n");
printk( "|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
(int)((dbg_info.snd.dma_buff_pcm_rm*)/(dbg_info.snd.dma_buff_pcm_len)),
(unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,
(int)((dbg_info.snd.dma_buff_dd_rm*)/(dbg_info.snd.dma_buff_dd_len)),
(unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,
(int)((dbg_info.snd.dma_buff_ddp_rm*)/(dbg_info.snd.dma_buff_ddp_len)),
(unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len ); printk( "+-----+------------------+------------------+------------------+------------------+\n\n");
} return ;
} /*Process debug info*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
static ssize_t audio_dbginfo_procfile_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos)
{
int len = ;
ssize_t ret_len = ; if(audio_info_buffer)
{
memset(audio_info_buffer, , MAX_BUF_RD_LEN);
len = audio_read_debug_info(audio_info_buffer);
ret_len = simple_read_from_buffer(ubuf, size, ppos, audio_info_buffer, len);
} return ret_len;
} static ssize_t audio_dbginfo_procfile_write(struct file *file, const char __user * buffer, size_t count, loff_t *ppos)
{
char buf[MAX_BUF_WT_LEN] = {};
char *eq_ch = NULL;
char *endp = NULL;
unsigned long value = ; if ((>=count) || (MAX_BUF_WT_LEN<count))
return ; if (copy_from_user(buf, buffer, count))
return -EFAULT; eq_ch = strstr(buf, "=");
if (NULL == eq_ch)
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
} value = simple_strtoul((char *)(eq_ch+), &endp, );
if ((eq_ch+) == endp || value >= INT_MAX)
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+));
return -EINVAL;
} switch(*buf)
{
case 'a':
{
if (strstr(buf, "ad_en"))
{
if (==value || ==value)
{
if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
{
printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
return -EFAULT;
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
return -EINVAL;
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
}
break;
}
case 'm':
{
if (strstr(buf, "monitor"))
{
if (==value || ==value)
{
g_dbg_show_en = value;
if (g_dbg_show_en)
{
if (mutex_lock_interruptible(&audio_dbg_mutex))
{
return(-ERESTARTSYS);
}
wake_up_interruptible(&audio_dbg_wq);
mutex_unlock(&audio_dbg_mutex);
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
return -EINVAL;
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
}
break;
}
case 'i':
{
if (strstr(buf, "interval"))
{
if (<value && >value)
{
g_dbg_show_interval = value;
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
return -EINVAL;
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
}
break;
}
default:
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
} #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
if (( != sscanf(buf, "ad_en=%d", &ad_en)) && (==ad_en || ==ad_en))
{
return ;
}
if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
{
printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
return ;
}
printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
#endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */ return count;
}
#else
static int audio_dbginfo_procfile_read(char*buffer, char**buffer_localation, off_t offset,int buffer_length,int* eof, void *data )
{
int len = ;
len = audio_read_debug_info(buffer);
*eof = ;
return len;
} static int audio_dbginfo_procfile_write(struct file *filp, const char *buffer,unsigned long count,void *data)
{
char buf[MAX_BUF_WT_LEN] = {};
char *eq_ch = NULL;
char *endp = NULL;
unsigned long value = ; if ((>=count) || (MAX_BUF_WT_LEN<count))
return ; if (copy_from_user(buf, buffer, count))
return -EFAULT; eq_ch = strstr(buf, "=");
if (NULL == eq_ch)
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
} value = simple_strtoul((char *)(eq_ch+), &endp, );
if ((eq_ch+) == endp || value >= INT_MAX)
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+));
return -EINVAL;
} switch(*buf)
{
case 'a':
if (strstr(buf, "ad_en"))
{
if (==value || ==value)
{
if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
{
printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
return -EFAULT;
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
return -EINVAL;
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
}
break;
case 'm':
if (strstr(buf, "monitor"))
{
if (==value || ==value)
{
g_dbg_show_en = value;
if (g_dbg_show_en)
{
if (mutex_lock_interruptible(&audio_dbg_mutex))
{
return(-ERESTARTSYS);
}
wake_up_interruptible(&audio_dbg_wq);
mutex_unlock(&audio_dbg_mutex);
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
return -EINVAL;
}
}
else
{
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
}
break;
default:
printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
return -EINVAL;
} #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
if (( != sscanf(buf, "ad_en=%d", &ad_en)) && (==ad_en || ==ad_en))
{
return ;
}
if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
{
printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
return ;
}
printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
#endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */ return count;
} #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
static const struct file_operations audio_debuginfo_fops = {
.read = audio_dbginfo_procfile_read,
.write = audio_dbginfo_procfile_write,
.llseek = default_llseek,
};
#endif static int audio_dbg_show_thread(void *param)
{
__s32 ret; for(;;)
{
if (mutex_lock_interruptible(&audio_dbg_mutex))
{
return(-ERESTARTSYS);
} /* Wait until we are allowed to show debug info.
*/
while (g_dbg_show_en == )
{
mutex_unlock(&audio_dbg_mutex);
if (wait_event_interruptible(audio_dbg_wq, (==g_dbg_show_en)))
{
return(-ERESTARTSYS);
}
if (mutex_lock_interruptible(&audio_dbg_mutex))
{
return(-ERESTARTSYS);
}
} ret = audio_show_debug_info(); if (ret < )
{
g_dbg_show_en = ;
printk("\033[40;31m%s->%s.%u, audio_show_debug_info failed!.\033[0m\n", __FILE__, __FUNCTION__, __LINE__);
}
mutex_unlock(&audio_dbg_mutex); msleep(g_dbg_show_interval*);
} return();
} int audio_debug_procfs_init(void)
{
audio_info_buffer = kmalloc(MAX_BUF_RD_LEN, GFP_KERNEL);
if (NULL == audio_info_buffer)
{
printk("kmall audio_info_buffer %d failed!!\n", MAX_BUF_RD_LEN);
return -;
}
mutex_init(&audio_dbg_mutex);
init_waitqueue_head(&audio_dbg_wq); audio_proc_dir = proc_mkdir(AUDIO_DEBUG_PROC_DIR, NULL);
if (audio_proc_dir == NULL) {
printk("audio_debug_procfs_init create dir audio failed!!\n");
kfree(audio_info_buffer);
return -;
} #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
/*For Debug info*/
audio_proc_dbginfo_file = proc_create(AUDIO_DEBUG_PROC_INFO,,audio_proc_dir, &audio_debuginfo_fops);
#else
/*For Debug info*/
audio_proc_dbginfo_file = create_proc_entry(AUDIO_DEBUG_PROC_INFO,,audio_proc_dir);
#endif
if(audio_proc_dbginfo_file == NULL)
{
remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
kfree(audio_info_buffer);
printk("Error:could not initialize /proc/%s/%s\n", AUDIO_DEBUG_PROC_DIR, AUDIO_DEBUG_PROC_INFO);
return -;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
audio_proc_dbginfo_file->read_proc = audio_dbginfo_procfile_read;
audio_proc_dbginfo_file->write_proc = audio_dbginfo_procfile_write;
#endif audio_deca_dev=(struct deca_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_DECA);
audio_snd_dev=(struct snd_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_SND); audio_dbg_show_thread_ptr = kthread_create(audio_dbg_show_thread, NULL, "audio_dbg"); if (IS_ERR(audio_dbg_show_thread_ptr))
{
printk("%s,%d\n", __FUNCTION__, __LINE__);
remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
kfree(audio_info_buffer);
return(PTR_ERR(audio_dbg_show_thread_ptr));
} wake_up_process(audio_dbg_show_thread_ptr); return ;
} void audio_debug_procfs_exit(void)
{
remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL); if (audio_info_buffer)
kfree(audio_info_buffer); return ;
}
今天刚好加了一个procfs的目录,用于调试自己的驱动,使用方法如下:
目前支持如下几个命令:
cat /proc/audio/debuginfo --》查看audio信息
echo "ad_en=1" > /proc/audio/debuginfo --》动态打开/关闭audio desc,ad_en参数只能为0或1
echo "monitor=1" > /proc/audio/debuginfo --》wake up内核线程audio_dbg,默认每秒打印一次audio信息,monitor参数只能为0或1
echo "interval=5" > /proc/audio/debuginfo --》设置monitor打印的时间间隔(单位:秒),interval参数范围为[1,100]
audio打印信息如下:(其中表格记录的是audio各个buff的使用情况:剩余数据量百分比(剩余数据量/buff总大小),主要用于debug buff堵住的情况)
# cat /proc/audio/debuginfo desc enable : no
deca state : IDLE()
deca sub state : IDLE()
snd state : IDLE()
snd sub state : IDLE()
+-----+------------------+------------------+------------------+------------------+
|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |
+-----+------------------+------------------+------------------+------------------+
|BS |%(/0c800) |%(/0c800) | | |
+-----+------------------+------------------+------------------+------------------+
|CB |%(/000c8) |%(/000c8) | | |
+-----+------------------+------------------+------------------+------------------+
|SYNC |%(/) |%(/) |%(/) |%(/) |
+-----+------------------+------------------+------------------+------------------+
|DMA |%(/) | |%(/) |%(/) |
+-----+------------------+------------------+------------------+------------------+
linux内核debug的一种方式:procfs的更多相关文章
- Linux 内核睡眠的几种方式
译至:http://geeki.wordpress.com/2010/10/30/ways-of-sleeping-in-linux-kernel/ 在Linux中睡眠有2-3种不同的方法. 睡眠的第 ...
- 设置 Linux 下打印机的几种方式
设置 Linux 下打印机的几种方式 一.使用 cups 进行设置 如若遇到 cups 也没有驱动的话可以前往 openprinting.org 找寻对应驱动. 二.前往 official 下载驱动 ...
- linux创建文件的四种方式(其实是两种,强行4种)
linux创建文件的四种方式: 1.vi newfilename->i->编辑文件->ESC->:wq! 2.touch newfilename 3.cp sourcePath ...
- Linux 软件安装的三种方式
Linux 软件安装的三种方式 1.yum 语法格式: yum -y install package.name -y yes # 遇到提示自动输入yes 案例: 安装ifconfig命 ...
- Linux 安装 Nodejs 的两种方式
Linux 安装 Nodejs 的两种方式 目录 Linux 安装 Nodejs 的两种方式 一.压缩包安装 Nodejs 二.源码编译安装 Nodejs 一.压缩包安装 Nodejs 下载 Node ...
- Linux下定时执行任务的几种方式
如果说我说如果,你的某一个目录下会经常的生成一些垃圾文件,比如访问日志.错误日志.core文件,而你又不想过几分钟就去手动检查一下,那么可以使用定时执行任务的方式来解决.目前我所知道的可以执行定时任务 ...
- linux异步IO的两种方式【转】
转自:https://blog.csdn.net/shixin_0125/article/details/78898146 知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个C ...
- Linux内核替换的一种简单方法
前言 使用现有centos的镜像,在海光机器上出现了无法运行的情况,grub引导后就只剩下光标一直在闪,无任何字符输出.这种情况大概率是因为Linux的内核无法运行在海光的CPU上所导致的. 已得知L ...
- Linux进程通信的几种方式总结
进程通信的目的 数据传输 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程需要向另一个或一组进程发 ...
随机推荐
- SQL 除去数字中多于的0
/* 除掉多于的0 */ CREATE FUNCTION [dbo].[fn_ClearZero] ( ) ) ) AS BEGIN ); IF (@inValue = '') SET @return ...
- 十三道Python练习题
一.完美立方 编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a^3= b^3 + c^3 + d^3,其中a,b,c,d 大于 1, 小于等于N. 输入 ...
- 10道Python常见面试题
1.MySQL索引种类 1.普通索引 2.唯一索引 3.主键索引 4.组合索引 5.全文索引 2.索引在什么情况下遵循最左前缀的规则? 最左前缀原理的一部分,索引index1:(a,b,c),只会走a ...
- angular获取时间
获取24小时制的时间<h1> {{time}} </h1> <script> angular.module('app', []) .controller('ctrl ...
- JS实现16进制和RGB转换
作为前端开发而言,不可避免的会遇到颜色取值,字符串和数字直接的转换,博主为此写了一个小工具,实现色值之间的在线转换. 前置知识点: parseInt, toString parseInt(value ...
- 多线程学习笔记(三) BackgroundWorker 暂停/继续
BackgroundWorker bw; private ManualResetEvent manualReset = new ManualResetEvent(true); private void ...
- Linux 信号量之Posix基于内存的信号量
信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能. 信号量有三种: Posix有名字的信号量 Posix基于内存的信号量 System V信号量 信号量比互斥锁高级,互斥锁 ...
- Centos7服务器搭建网络家园和论坛
环境:Centos7 工具:mysql,php,httpd 目的:熟练掌握httpd服务器搭建和个服务器之间的配合. 有兴趣的朋友可以来实践一下,我会提供各种源码进行搭建. 网络家园和论坛源码:htt ...
- 002-OpenStack-认证服务
OpenStack-认证服务 [基于此文章的环境]点我快速打开文章 1.安装和配置 控制节点(controller) 1.1 创库授权 keystone mysql CREATE DATABASE k ...
- Windows | Ubuntu 18.04安装Visual Studio Code
Visual Studio Code是一款很好的开源跨平台代码编辑器,这里使用 tarball 格式文件来安装(免安装), 首先下载 .tar.gz 文件包,点击下载, 可自行在官网下载 将文件包解 ...