crazyhadoop 发表于 2014-04-08 20:24

Linux系统开发那点事儿 分享经验得牛人力作!(获奖名单已公布-2014-5-28)

获奖名单已公布,详情请看:http://bbs.chinaunix.net/thread-4140163-1-1.html

话题背景:

Linux系统编程想必大家都已不陌生,高手众多,不过有些坎,即使高手也难逃一劫,前仆后继的被绊一跤。“系统编程”是指编写系统软件,其代码在底层运行,直接跟内核和核心系统库对话。比如说Linux系统调用和底层函数说明,如C库定义的函数。作为基础,系统程序员需要对Linux文件系统、I/O、缓存、进程、内存都有了解,要想成为大家则需精通。大家可以聊聊自己在开发过程中遇见的各种诡异的情景,奇葩的错误,比如api的使用死角,例如syslog传入的数据没有对%进行转义,内存爆栈,网络洪水,自己把自己DDOS打死;等等各种印象深刻的事情。

今日话题:

      1. 系统开发中遇见的那些头疼的问题
      2. 系统开发过程中的收获
      3. 如何做好Linux 系统开发


活动时间:

2014-4-8至2014-5-15

活动奖励:

我们将会选择几位突出的网友赠送一本常读常新的书籍《Linux系统编程》第二版,作者是大名鼎鼎Robert Love
这个作者可是非常有名,Google的高级工程师,写的书质量极高,书虽然不厚,内容却都是干货
Linux系统编程经典之作,根据Linux内核3.0更新 !
Linux程序设计方面的传奇人物Robert Love力作 !

奖品简介:
Linux系统编程(第2版)
http://images.china-pub.com/ebook3765001-3770000/3769917/zcover.jpg
作者: (美)Robert Love   
译者: 祝洪凯 李妹芳 付途
出版社:人民邮电出版社
ISBN:9787115346353
上架时间:2014-4-18
出版日期:2014 年4月
开本:16开
页码:420

图书样张:








(样张文件需要两个都要下载解压才能打开)






流氓无产者 发表于 2014-04-09 09:35

问题倒多,可惜大部分是自己的问题

阿注哥 发表于 2014-04-09 10:13

我遇到的这个问题其实应该不算个问题,但在我刚开始学多线程编程的时候却困扰了我很久,在网上也没找到答案,或者说没有直接的答案,后来是自己去读了部分nptl源代码后才明白原因,虽然费时很多,但也收获良多。
问题很简单,就是关于线程取消的操作,在某种情况下,线程不管怎样都不能退出,问题肯定是出在锁上,但始终找不到死锁的地方,先帖段代码:#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t lock;
pthread_cond_t cond;
void thrd_cleanup()
{
        printf("thread canceled\n");

        pthread_mutex_unlock(&lock);
}

void thrd_func()
{
        pthread_cleanup_push(thrd_cleanup, NULL);
        printf("thread: enter\n");
        pthread_mutex_lock(&lock);
        pthread_cond_wait(&cond, &lock);
        pthread_mutex_unlock(&lock);
        pthread_cleanup_pop(0);
        printf("thread: exit\n");
}

int main(int argc, char *argv[])
{
        pthread_t tid;

        pthread_mutex_init(&lock, NULL);
        pthread_cond_init(&cond, NULL);

        for (int i = 0; i < 4; ++i) {
                int ret = pthread_create(&tid, NULL, thrd_func, NULL);
                if (ret) {
                        perror("pthread_create");
                }
        }

        sleep(3);

        pthread_mutex_lock(&lock);

        for (int i = 0; i < 4; ++i) {
                printf("before cancel\n");
                pthread_cancel(tid);
                pthread_join(tid, NULL);
                printf("after cancel\n");
        }

        pthread_mutex_unlock(&lock);

        sleep(6);

        return 0;
}上面代码得到的输出为thread: enter
thread: enter
thread: enter
thread: enter
before cancel可见在第一个线程退出的时候出了问题,一开始就几乎可以肯定是锁这出了问题,可一直找不到原因,attach该进程,得到的结果为(gdb) bt
#00xb772f424 in __kernel_vsyscall ()
#10xb7707e1c in pthread_join () from /lib/i386-linux-gnu/libpthread.so.0
#20x080489f4 in main (argc=1, argv=0xbfe68a24) at main.c:67可见,程序在调用pthread_join后阻塞了,再查看当前进程中的线程:(gdb) info threads
Id   Target Id         Frame
4    Thread 0xb6d52b40 (LWP 5658) "foo" 0xb772f424 in __kernel_vsyscall ()
3    Thread 0xb6551b40 (LWP 5659) "foo" 0xb772f424 in __kernel_vsyscall ()
2    Thread 0xb5d50b40 (LWP 5660) "foo" 0xb772f424 in __kernel_vsyscall ()
* 1    Thread 0xb75546c0 (LWP 5656) "foo" 0xb772f424 in __kernel_vsyscall ()显示已经有一个线程成功退出,而查看进程的/proc文件系统信息得到的却是:$ls /proc/5656/task
56565657565856595660这却说明刚才的那个线程没有完全退出,当时我觉得这是相当诡异的,所谓百思不得其解啊,最后经过分析nptl关于pthread_cancel操作的源码后,终于找到了原因:

我们在进入线程的时候注册了线程清理理函数,随后进入等待状态,注意这时候主线程已经持有锁了,并调用pthread_cancel和pthread_join,这个时候nptl的实现中需要再次持有该锁,这时候问题就出现了,主线程持有锁并等待pthread_join的结束,而nptl库需要先拿到锁才能返回,这就永远不会结束,导致上面的问题。

经过这个问题之后,觉得多线程编程真是个头疼的问题,稍有不甚就会出现各种诡异的问题,尤其对于初学者,经验不足,解决起这些问题是费时费力又不一定有效果。

jimmy-_-lixw 发表于 2014-04-09 10:55

支持活动,好活动探讨linux开源系统。

friendmine 发表于 2014-04-09 10:59

1. 系统开发中遇见的那些头疼的问题
   多线程, 用pthread的时候, 栈开小了, 出了错是panic 吧.
   tcp/ip 数据同步出问题, x86到power时, 映射数据会有大小端转换

2. 系统开发过程中的收获
   解决方案没把握时, 一定要写个demo来验证一下.

sxcong 发表于 2014-04-09 13:37

最大的坑就是那个著名的 a.out,一定要./a.out才可以执行。有多少初学者, gcc hello.c一次写对编译成功并执行成功的?

hellioncu 发表于 2014-04-09 13:47

mmap失败返回的不是想当然的NULL,而是MAP_FAILED(-1):mrgreen:

timespace 发表于 2014-04-09 14:27

回复 3# 阿注哥
分析NPTL源码解决问题,很强大啊!
个人使用多线程时恪守两个原则:
1. “thread is evil”,能不用就不用。Linux/UNIX下,多线程比多进程的优势并没有教科书理论阐释的那么美好,不过多线程确实可以简化共享数据结构的实现,看看多进程五花八门的IPC就知道了。
2. 使用简单的核心API,少用高大上。理解mutex/condition variable/semaphore API就可以解决多数问题,当想用push/pop/cancel等等偏门API时,反省自己的代码架构,通常可以避免之。

   

阿注哥 发表于 2014-04-09 14:49

回复 8# timespace


    linux的线程用轻量进程实现,实则区别不大,记得看过一篇文章,详细介绍其区别,也说了没特别的必要性就尽量避免!那么花了我好多时间才搞明白,算是印象深刻的一次经历了。

freshriver 发表于 2014-04-10 09:15

做C语言开发有一段时间了,我的一些经验分享给大家:

1 C就是C,不要在C中实现try ... catch, 如果实在避不开,用一下setjmp longjunp,不建议大量使用,多用if做判断更好

2 C就是C,不要在C中试图实现类似C++/Java等语言中的类,C吗?简单点更好

3 内存管理,如果不能简单到每次申请大小都是固定长度字节的内存,那就别自己管理内存了,有更好的工具可以使用,比如:Google Performance Tools
页: [1] 2 3 4 5 6 7
查看完整版本: Linux系统开发那点事儿 分享经验得牛人力作!(获奖名单已公布-2014-5-28)