1. 调试的时候可以使用的宏
printf("%s%s %d\n",__FILE__,__func__,__LINE__);
/* head.h */
#define MY_PRINT_DEBUG_ON
#define MY_PRINT_ON
#ifdef MY_PRINT_DEBUG_ON
#ifdef MY_PRINT_ON
#define my_print( a ) do{ printf( a );\
printf( "File:%s Func: %s Line: %d\n", \
__FILE__, __FUNC__, __LINE__ ); \
}while(0)
#else
#define my_print( a )
#endif //end for MY_PRINT_ON
#endif //end for MY_PRINT_DEBUG_ON
2. 计算指定位数共占用的字节数
nbyte = (bit + 7)>> 3;
3. 让宏定义能像函数一样有一个返回值的方法:
#define FUNC()\
({ \
int ret; \
............... \
ret; \
})
4. 给代码加上批量调试信息
先在想要调试的源码目录下执行:
cd sound
find -name '*.c' -exec sed-i '/)$/N;s#)\n{#)\n{\n\tprintk(\"my_debug: %s %d %s\\n\", __FILE__,__LINE__, __FUNCTION__);#' {} \;
#用)\n{来标志一个函数的开始
cd ..
调试完以后再执行find -name '*.c' -exec sed-i '/my_debug/d' {} \;
删除刚才加的那些调试信息。
5. 1,求两个集合的交集.(考官提示我是两个集合,要排序)
2,求26个英文字母的所有子集.(对应26bits,然后就行了)
二面就更简单了,一个是上边的指针问题,我连题都没仔细读一遍就稀里糊涂的说出俩答案,你说能过么.
二就是单链表逆转,噼里啪啦一套秒掉,直接叫了面试官检查,面试官看了一下让我解释一下核心代码.
6. 根据二叉树的前序和中序生成二叉树
/*bintree.c */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
structbintree {
struct bintree *left;
struct bintree *right;
char tag;
};
intnstrchr(const char *s, int len, char c)
{
int i;
for (i = 0; i < len; i++) {
if (s[i] == c) {
return i;
}
}
return -1;
}
intcreate_bintree(struct bintree **pnode, const char *before, const char *middle,int len)
{
struct bintree *node;
int i;
int retval;
if (len == 0) {
retval = -1;
}else {
i = nstrchr(middle, len, *before);
if (i == -1) {
retval = -1;
}else {
node = (struct bintree*)malloc(sizeof(struct bintree));
if (node == NULL) {
retval = -1;
}else {
retval = 0;
memset(node, 0,sizeof(struct bintree));
node->tag =*before;
if (i > 0) {
retval= create_bintree(&node->left, before + 1, middle, i);
}
if (retval ==0) {
if (i + 1 < len) {
retval = create_bintree(&node->right, before + i + 1, middle + i+ 1, len - i - 1);
}
}
if (retval == 0) {
*pnode= node;
}else {
free(node);
}
}
}
}
return retval;
}
voiddestroy_bintree(struct bintree **bintree)
{
if (*bintree != NULL) {
if ((*bintree)->left !=NULL) {
destroy_bintree(&(*bintree)->left);
}
if ((*bintree)->right != NULL) {
destroy_bintree(&(*bintree)->right);
}
free(*bintree);
*bintree = NULL;
}
}
voidprint_bintree_after(struct bintree *bintree)
{
if (bintree != NULL) {
if (bintree->left != NULL) {
print_bintree_after(bintree->left);
}
if (bintree->right != NULL){
print_bintree_after(bintree->right);
}
putchar(bintree->tag);
}
}
intmain(void)
{
struct bintree *bt;
bt = NULL;
if (create_bintree(&bt,"EDBACHFG", "ABCDEFGH", 8) == 0) {
print_bintree_after(bt);
destroy_bintree(&bt);
return 0;
}
return -1;
}
7. 统计代码行数
不计空行:
for file in `find . -name"*.c"`
do
let n+=`grep -c . "$file"`
done
echo $n
计算空行:
for file in `find . -name "*.c"`
do
let n+=`grep -c ".*""$file"`
done
echo $n
8. 关于自旋锁的使用
spinlock_XXX有很多形式,有
spin_lock()/spin_unlock(),
spin_lock_irq()/spin_unlock_irq(),
spin_lock_irqsave/spin_unlock_irqrestore()
spin_lock_bh()/spin_unlock_bh()
local_irq_disable/local_irq_enable
local_bh_disable/local_bh_enable
那么,在什么情况下具体用哪个呢?这要看是在什么内核执行路径中,以及要与哪些内核
执行路径相互斥。我们知道,内核中的执行路径主要有:
1 用户进程的内核态,此时有进程context,主要是代表进程在执行系统调用
等。
2 中断或者异常或者自陷等,从概念上说,此时没有进程context,不能进行
context switch。
3 bottom_half,从概念上说,此时也没有进程context。
4 同时,相同的执行路径还可能在其他的CPU上运行。
这样,考虑这四个方面的因素,通过判断我们要互斥的数据会被这四个因素中
的哪几个来存取,就可以决定具体使用哪种形式的spinlock。如果只要和其他CPU
互斥,就要用spin_lock/spin_unlock,如果要和irq及其他CPU互斥,就要用
spin_lock_irq/spin_unlock_irq,如果既要和irq及其他CPU互斥,又要保存
EFLAG的状态,就要用spin_lock_irqsave/spin_unlock_irqrestore,如果
要和bh及其他CPU互斥,就要用spin_lock_bh/spin_unlock_bh,如果不需要和
其他CPU互斥,只要和irq互斥,则用local_irq_disable/local_irq_enable,
如果不需要和其他CPU互斥,只要和bh互斥,则用local_bh_disable/local_bh_enable,
等等。
9. spin_unlock_irq会开中断,所以在使用spin_lock_irq时要确保中断也是启用的
10. LDD 159页不明白,wait_queue_head_t的使用
11.modprobe分析/lib/modules/X.Y.Z/modules.dep加载它所依赖的模块
12.信号量可用只被一个进程打开 if(down_trylock(&xxx_lock)) return –EBASY