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字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程需要向另一个或一组进程发 ...
随机推荐
- MySql数据库中正则表达式
命令 说明 ^ 在字符的开启处进行匹配 $ 在字符的末尾处进行匹配 . 匹配任何字符(包括回车和新行) [-.] 匹配括号内的任意单个字符 [m-n] 匹配m到n之间的任意单个字符,例如[0-9],[ ...
- mask-rcnn代码解读(七):display(self)函数的解析
如和将class中定义的变量打印或读取出来,受maskrcnn的config.py的启示,我将对该函数进行解释. 我将介绍该函数前,需要对一些名词进行解释,如下: ①Ipython:ipython是一 ...
- MongoDB常用数据库命令第三集
show dbs 查看已经存在的数据库 use 数据库名 切换到指定的数据库(无论数据库是否存在 均可切换成功) db 查看当前数据库 db.getCollectionNames() 查看当前数据库下 ...
- 使用qwt作曲线图——有网格线背景的画法
创建自己的QwtPlot (1) 增加一个类比如curvePlotWidget,继承自QwtPlot (2)代码示例 curvePlotWidget::curvePlotWidget(QWid ...
- JS-21点游戏
//21点游戏 let readline=require("readline-sync"); //清屏函数 let clear=()=>process.stdout.writ ...
- amanda安装
下载地址 http://www.amanda.org/download.php http://www.zmanda.com/download-amanda.php 编译安装 编译出错: error: ...
- pipenv 管理虚拟环境
pipenv --python 3.6 创建虚拟环境 vim Pipfile —> 修改源 为阿里云镜像 https://mirrors.aliyun.com/pypi/simple [pack ...
- Django Windows+IIS+wfastcgi 环境下部署
教程基于 Windows 10专业版 + Python3.6 + IIS + wfastcgi 之上部署Django2.2的,同样适用于Windows server2012服务器和Windows7及以 ...
- JS高阶---闭包应用(自定义JS模块)
[自定义JS模块] [闭包案例] (1)案例1 对应的模块文件 (2)案例2---使用匿名函数 对应的模块文件 案例2分析:因为内部函数引用了外部函数的变量,且存在嵌套关系,所以是闭包,分析结构图如下 ...
- 201871010131-张兴盼《面向对象程序设计(java)》第十六周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...