Apr27

【原创】使用Netbeans7.1静态编译应用程序

Author: leeon  Click: 6417   Comments: 0 Category: Linux C/C++编程  Tag: netbeans,static,compile,link,lib

最近项目使用到很多外部开源库,但是动态链接对于程序的移植和部署带来极大的不变,本人一直用netbeans写linux c/c++程序,但是静态链接并不好使,在配置选项中加上-static老是编译不通过提示头文件找不到。网上压根就没现成的讲解,自己摸索把问题搞定了。

1.首先把需要链接的静态库放到编写的代码同级目录中。

2.然后根据如图所示配置即可:

 

Mar25

Linux select函数学习笔记

Author: leeon  Click: 7164   Comments: 0 Category: Linux C/C++编程  Tag: select,io,fd_set

转载了一个比较容易理解select函数作用的解释:

理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。
(1)执行fd_set set; FD_ZERO(&set);则set用位表示是0000,0000。
(2)若fd=5,执行FD_SET(fd,&set);后set变为0001,0000(第5位置为1)
(3)若再加入fd=2,fd=1,则set变为0001,0011
(4)执行select(6,&set,0,0,0)阻塞等待
(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。

注意第五条中的fd=5被清空,说明只要是不活跃的文件描述符都会在select的阻塞被结束后从原有的文件描述集合fd_set中被去除。因此在socket使用select的场景下,是可以在while轮询中使用FD_ISSET宏来不断监听服务器端生成的socket文件描述符是否活跃。

Jan21

【转载】getchar()和EOF有关总结

Author: chinaunix  Click: 6336   Comments: 0 Category: Linux C/C++编程  Tag: getchar,eof
getchar()和EOF总结

大师级经典的著作,要字斟句酌的去读,去理解。以前在看K&R的The C Programming Language(SecondEdition)
第1.5节的字符输入/输出,被getchar()和EOF所迷惑了。可能主要还是由于没有搞清楚getchar()的工作原理和EOF的用法。因此,感觉很有必要总结一下,不然,很多琐碎的知识点长时间过后就会淡忘的,只有写下来才是最好的方法。
其实,getchar()最典型的程序也就几行代码而已。本人所用的环境是DebianGNU/Linux,在其他系统下也一样。
一、getchar的两点总结:
1.getchar是以行为单位进行存取的。
当用getchar进行输入时,如果输入的第一个字符为有效字符(即输入是文件结束符EOF,Windows下为组合键Ctrl+Z, Unix/Linux下为组合键Ctrl+D),那么只有当最后一个输入字符为换行符'\n'(也可以是文件结束符EOF,EOF将在后面讨论)时, getchar才会停止执行,整个程序将会往下执行。譬如下面程序段:
while((c = getchar()) != EOF){
putchar(c);
}
执行程序,输入:abc,然后回车。则程序就会去执行puchar(c),然后输出abc,这个地方不要忘了,系统输出的还有一个回车。然后可以继续输入,再次遇到换行符的时候,程序又会把那一行的输入的字符输出在终端上。
对于getchar,肯定很多初学的朋友会问,getchar不是以字符为单位读取的吗?那么,既然我输入了第一个字符a,肯定满足while循环(c = getchar()) != EOF的条件阿,那么应该执行putchar(c)在终端输出一个字符a。不错,我在用getchar的时候也是一直这么想的,但是程序就偏偏不着样执行,而是必需读到一个换行符或者文件结束符EOF才进行一次输出。
对这个问题的一个解释是,在大师编写C的时候,当时并没有所谓终端输入的概念,所有的输入实际上都是按照文件进行读取的,文件中一般都是以行为单位的。因此,只有遇到换行符,那么程序会认为输入结束,然后采取执行程序的其他部分。同时,输入是按照文件的方式存取的,那么要结束一个文件的输入就需用到EOF (Enf Of File). 这也就是为什么getchar结束输入退出时要用EOF的原因。
2.getchar()的返回值一般情况下是字符,但也可能是负值,即返回EOF。
这里要强调的一点就是,getchar函数通常返回终端所输入的字符,这些字符系统中对应的ASCII值都是非负的。因此,很多时候,我们会写这样的两行代码:
char c;
c = getchar();
这样就很有可能出现问题。因为getchar函数除了返回终端输入的字符外,在遇到Ctrl+D(Linux下)即文件结束符EOF时,getchar ()的返回EOF,这个EOF在函数库里一般定义为-1。因此,在这种情况下,getchar函数返回一个负值,把一个负值赋给一个char型的变量是不正确的。为了能够让所定义的变量能够包含getchar函数返回的所有可能的值,正确的定义方法如下(K&R C中特别提到了这个问题):
int c;
c = getchar();
二、EOF的两点总结(主要指普通终端中的EOF)
1.EOF作为文件结束符时的情况:
EOF虽然是文件结束符,但并不是在任何情况下输入Ctrl+D(Windows下Ctrl+Z)都能够实现文件结束的功能,只有在下列的条件下,才作为文件结束符。
(1)遇到getcahr函数执行时,要输入第一个字符时就直接输入Ctrl+D,就可以跳出getchar(),去执行程序的其他部分;
(2)在前面输入的字符为换行符时,接着输入Ctrl+D;
(3)在前面有字符输入且不为换行符时,要连着输入两次Ctrl+D,这时第二次输入的Ctrl+D起到文件结束符的功能,至于第一次的Ctrl+D的作用将在下面介绍。
其实,这三种情况都可以总结为只有在getchar()提示新的一次输入时,直接输入Ctrl+D才相当于文件结束符。
2.EOF作为行结束符时的情况,这时候输入Ctrl+D并不能结束getchar(),而只能引发getchar()提示下一轮的输入。
这种情况主要是在进行getchar()新的一行输入时,当输入了若干字符(不能包含换行符)之后,直接输入Ctrl+D,此时的Ctrl+D并不是文件结束符,而只是相当于换行符的功能,即结束当前的输入。以上面的代码段为例,如果执行时输入abc,然后Ctrl+D,程序输出结果为:
abcabc
注意:第一组abc为从终端输入的,然后输入Ctrl+D,就输出第二组abc,同时光标停在第二组字符的c后面,然后可以进行新一次的输入。这时如果再次输入Ctrl+D,则起到了文件结束符的作用,结束getchar()。
如果输入abc之后,然后回车,输入换行符的话,则终端显示为:
abc //第一行,带回车
abc //第二行
//第三行
其中第一行为终端输入,第二行为终端输出,光标停在了第三行处,等待新一次的终端输入。
从这里也可以看出Ctrl+D和换行符分别作为行结束符时,输出的不同结果。
EOF的作用也可以总结为:当终端有字符输入时,Ctrl+D产生的EOF相当于结束本行的输入,将引起getchar()新一轮的输入;当终端没有字符输入或者可以说当getchar()读取新的一次输入时,输入Ctrl+D,此时产生的EOF相当于文件结束符,程序将结束getchar()的执行。
【补充】本文第二部分中关于EOF的总结部分,适用于终端驱动处于一次一行的模式下。也就是虽然getchar()和putchar()确实是按照每次一个字符 进行的。但是终端驱动处于一次一行的模式,它的输入只有到“\n”或者EOF时才结束,因此,终端上得到的输出也都是按行的。如果要实现终端在读一个字符就结束输入的话,下面的程序是一种实现的方法(参考《C专家编程》,略有改动):
/*Edit by Godbach
CU Blog: http://blog.chinaunix.net/u/33048/
*/
#include stdio.h>
#include stdlib.h>
int
main(void)
{
int c;
/* 终端驱动处于普通的一次一行模式 */
system("stty raw");

/* 现在的终端驱动处于一次一个字符模式 */
c = getchar();
putchar();

/* 终端驱动处又回到一次一行模式 */
system("stty cooked");

return 0;
}
编译运行该程序,则当如入一个字符时,直接出处一个字符,然后程序结束。
由此可见,由于终端驱动的模式不同,造成了getchar()输入结束的条件不一样。普通模式下需要回车或者EOF,而在一次一个字符的模式下,则输入一个字符之后就结束了。
希望本文可以对初学C的朋友提供一点帮助,也希望能和其他朋友进行交流。其中理解不对的地方若能得到指正和建议,本人将不胜感激。同时,本文参考了chinaunix.net关于getchar讨论的帖子和一位博友的文章,链接地址分别为:
http://blog.chinaunix.net/u/9861/showart_64652.html
http://bbs.chinaunix.net/viewthread.php?tid=679688&extra=&page=1
Nov30

【转载】Linux下动态链接库so文件覆盖导致coredump问题的分析

Author: ifreax  Click: 12166   Comments: 0 Category: Linux C/C++编程  Tag: coredump,so,cp,linux

尝试解答以下问题:

      1.为什么cp的方式更新运行中进程的so,程序会coredump

      2.采用什么方式更新已经加载了的so,就可以避免coredump

 

我们的公共组件绝大部分都支持so形式的自定义插件,比如s++,qzhttp,ttc。在不停进程更新so的时候往往会产生coredump,并且肯定core得莫名其妙,core得让人心碎。

 

先看一下用cp的方式更新so的时候发生了什么事情

strace cp new.so old.so #strace是人间利器


发现老的sotrunc了,这个过程发生的具体的事情是:

      1.应用程序通过dlopen打开so的时候,kernel通过mmapso加载到进程地址空间,对应于vma里的几个page.

      2.在这个过程中loader会把so里面引用的外部符号例如malloc printf等解析成真正的虚存地址。

      3.socp覆盖时,确切地说是被trunc时,kernel会把so文件在虚拟内的页purge 掉。

      4.当运行到so里面的代码时,因为物理内存中不再有实际的数据(仅存在于虚存空间内),会产生一次缺页中断。

      5.Kernelso文件中copy一份到内存中去,a)但是这时的全局符号表并没有经过解析,当调用到时就产生segment fault ,  b)如果需要的文件偏移大于新的so的地址范围,就会产生bus error.

 

所以,如果用相同的so去覆盖

      A) 如果so 里面依赖了外部符号,coredump

      B) 如果so里面没有依赖外部符号,运气不错,不会coredump

 

所有问题的产生都是因为sotrunc了一把,所以如果不用turnc的方式就避免这个问题。Ok,该我们的install 上场了。

strace install new.so old.so



install 的方式跟cp不同,先unlinkcreat,当unlink的时候,已经map的虚拟空间vma中的inode结点没有变,只有inode结点的引用计数为0是,kernel才把它干掉。

也就是新的so和旧的so用的不是同一个inode结点,所以不会相互影响。这时只有得启程序才会使用到新的so。所以采用这种方式的话就可以避免先stop进程,更新so,再重启进程这样比较耗时的操作。

分类

标签

归档

最新评论

Abyss在00:04:28评论了
Linux中ramdisk,tmpfs,ramfs的介绍与性能测试
shallwe99在10:21:17评论了
【原创】如何在微信小程序开发中正确的使用vant ui组件
默一在09:04:53评论了
Berkeley DB 由浅入深【转自架构师杨建】
Memory在14:09:22评论了
【原创】最佳PHP框架选择(phalcon,yaf,laravel,thinkphp,yii)
leo在17:57:04评论了
shell中使用while循环ssh的注意事项

我看过的书

链接

其他

访问本站种子 本站平均热度:8823 c° 本站链接数:1 个 本站标签数:464 个 本站被评论次数:94 次