免费注册 查看新帖 |

Chinaunix

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

请教linux内核中goto语句的问题! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-05-13 16:01 |只看该作者 |倒序浏览
在linux内核中goto出现的频率很高,书上说是考虑到内核的执行效率。
但在下面的函数中,如果将goto换成return,那不更直接?
请大虾指教!
asmlinkage int sys_execve(struct pt_regs regs)
{
        int error;
        char * filename;

        filename = getname((char *) regs.ebx);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
        error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
        if (error == 0)
                current->;ptrace &= ~PT_DTRACE;
        putname(filename);
out:
        return error;
}

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2003-05-14 10:14 |只看该作者

请教linux内核中goto语句的问题!

当然不是!内核中编程和应用层大大不一样,你还忘了内核中为什么要大量用goto语句的另一个重要原因,就是内核中经常会牵涉到分配内存空间,而内核页的大小是有限的,内核堆栈空间也仅仅只有8k字节而已,如果已经分配了的空没有释放就会引起大量内存泄漏问题,在你这个例子中,我们分析一下:
asmlinkage int sys_execve(struct pt_regs regs)
{
int error;
char * filename;

filename = getname((char *) regs.ebx); //仔细看这句,getname函数是在内核中分配空间,然后用strncpy_from_user宏从应用层把regs.ebx传进内核
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out; //仔细想想如果你这里直接return了,那么getname函数分配的空间谁来释放?这样做会引起系统不稳定,严重会导致当机
error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &s);
if (error == 0)
current->;ptrace &= ~PT_DTRACE;
putname(filename);//这句相当重要,putname函数是一个宏,他释放前面getname函数分配的内核空间
out:
return error;
}


明白了么?所以千万不要以应用层的观点来编写内核程序,在内核写程序一定要严谨,而且要对内核非常熟悉,内核中还牵涉到很多的锁,如果你加了锁,然后在解锁之前就return了也会出问题,所以一定要借助goto语句来实现这个严谨的特性。

论坛徽章:
0
3 [报告]
发表于 2003-05-14 12:52 |只看该作者

请教linux内核中goto语句的问题!

十分感谢!
goto能实现内存释放?

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
4 [报告]
发表于 2003-05-14 14:44 |只看该作者

请教linux内核中goto语句的问题!

倒,看来你还没明白,goto不能释放内存,但是利用goto语句可以使程序严谨,你仔细看看上面的例子,用了goto,不论程序走什么分支,分配了的内存都得到了释放。如果直接return,那么前面分配的空间就在没释放就退出程序了,你自己想想吧

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
5 [报告]
发表于 2003-05-14 14:58 |只看该作者

请教linux内核中goto语句的问题!

我们看看我写的这个程序片断,这是在内核中的一个遍历双向循环链表的操作,在内核中
我们操作链表一定要加锁,以防止其他进程占用这块内存引起kernel panic。

  1. ...
  2. spin_lock(&list_lock);
  3. list_for_each(p,&user_access_list){
  4.         struct k_user_access *t = list_entry(p,struct k_user_access,a_list);
  5.         if(getpath(file,f))
  6.         {
  7.                 printk("Can not get full pathname\n");
  8.                 ret= -EPERM;/*我们看看这个程序分支,如果进入if这个分支,我们要返回一个
  9.                               错误-EPERM,如果这里我们直接用return -EPERM;的话,程序就
  10.                               退出了,我看看前面的spin_lock(&list_lock);这个自旋锁是不
  11.                               是还没解开?所以这是很危险的。*/
  12.                 goto out;/*我们用goto语句,让程序到out的地方执行,看看我们解锁了然后再return*/
  13.         }
  14. }
  15. ret = 0;
  16. out:
  17. spin_unlock(&list_lock);
  18. return ret;
复制代码

你可以看看这个程序任何一个分支都是不会出现上了锁而没解锁就退出程序的现象,这就goto语句的
作用,我们分配内存释放内存的道理也是一样的。如果你还没明白,那我就没办法啦。

论坛徽章:
0
6 [报告]
发表于 2003-05-14 18:33 |只看该作者

请教linux内核中goto语句的问题!

谢谢大虾的指教,在你给的例子里goto-->;out:后面跟有解锁的操作---这个当然应该goto了,它是goto完了之后的事情。但实际上内核中还有不少out处(我提问的那个函数里面)后面直接跟return error,这样的话got out:不就直接等于return error了吗?这中间有地方进行内存释放?由于小生初学,请不吝赐教。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
7 [报告]
发表于 2003-05-15 10:33 |只看该作者

请教linux内核中goto语句的问题!

对,并不是所有的goto语句都一定为了释放内存或者解锁,有的则是为了程序便于维护和阅读。

论坛徽章:
0
8 [报告]
发表于 2003-05-15 11:29 |只看该作者

请教linux内核中goto语句的问题!

十分感谢 

论坛徽章:
0
9 [报告]
发表于 2003-05-15 11:35 |只看该作者

请教linux内核中goto语句的问题!

呵呵,大鹰讲述的真是深入浅出啊。顶一下

论坛徽章:
0
10 [报告]
发表于 2003-05-15 12:43 |只看该作者

请教linux内核中goto语句的问题!

[quote]原帖由 "e4gle"]对,并不是所有的goto语句都一定为了释放内存或者解锁,有的则是为了程序便于维护和阅读。[/quote 发表:
大鹰,那么arcsiny提出的那段代码里面因为out:是在putname()的后面,是不是getname()请求的空间实际上并没有得到释放?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP