Archive

Posts Tagged ‘C++’

C语言如何编译出一个不需要操作系统的程序

January 3rd, 2018 No comments

来个更短的,没有其他乱七八糟的东西,只有一个简短的 C文件,不需要 linux 环境:

miniboot.c

asm(".long 0x1badb002, 0, (-(0x1badb002 + 0))");

unsigned char *videobuf = (unsigned char*)0xb8000;
const char *str = "Hello, World !! ";

int start_entry(void)
{
    int i;
    for (i = 0; str[i]; i++) {
        videobuf[i * 2 + 0] = str[i];
        videobuf[i * 2 + 1] = 0x17;
    }
    for (; i < 80 * 25; i++) {
        videobuf[i * 2 + 0] = ' ';
        videobuf[i * 2 + 1] = 0x17;
    }
    while (1) { }
    return 0;
}

编译:

gcc -c -fno-builtin -ffreestanding -nostdlib -m32 miniboot.c -o miniboot.o
ld -e start_entry -m elf_i386 -Ttext-seg=0x100000 miniboot.o -o miniboot.elf

运行:

qemu-system-i386 -kernel miniboot.elf

结果:

满足条件:

  • 只用纯 C 开发,可以使用 gcc 编译
  • 编译出来的东西真的可以运行
  • 不需要依赖操作系统
  • 不需要包含系统调用的 glibc
  • 连 libgcc 都不需要

解释一下:

Read more…

Categories: 编程技术 Tags: ,

如何实现一个真正高性能的spin_lock?

February 21st, 2017 No comments

应用层用spinlock的最大问题是不能跟kernel一样的关中断(cli/sti),假设并发稍微多点,线程1在lock之后unlock之前发生了时钟中断,一段时间后才会被切回来调用unlock,那么这段时间中另一个调用lock的线程不就得空跑while了?这才是最浪费cpu时间的地方。所以不能关中断就只能sleep了,怎么着都存在巨大的冲突代价。

尤其是多核的时候,假设 Kernel 中任务1跑在 cpu1上,任务 2跑在 cpu2上,任务1进入lock之前就把中断关闭了,不会被切走,调用unlock的时候,不会花费多少时间,cpu2上的任务2在那循环也只会空跑几个指令周期。

看看 Kernel 的 spinlock:

#define _spin_lock_irq(lock) \
do { \
    local_irq_disable(); \
    preempt_disable(); \
    _raw_spin_lock(lock); \
    __acquire(lock); \
} while (0)

看到里面的 local_irq_disable() 了么?实现如下:

#define local_irq_disable() \
    __asm__ __volatile__("cli": : :"memory") 

倘若不关闭中断,任务1在进入临界区的时候被切换走了,50ms以后才能被切换回来,即使原来临界区的代码只需要0.001ms就跑完了,可cpu2上的任务2还会在while那里干耗50ms,所以不能禁止中断的话只能用 sleep来避免空跑while浪费性能。

所以不能关闭中断的应用层 spinlock 是残废的,nop都没大用。

不要觉得mutex有多慢,现在的 mutex实现,都带 CAS,首先会在应用层检测冲突,没冲突的话根本不会不会切换到内核态,直接用户态就搞定了,即时有冲突也会先尝试spinlock一样的 try 几次(有限次数),不行再进入休眠队列。比傻傻 while 下去强多了。

Categories: 编程技术 Tags: ,

为何很多 C++开源库都爱自己实现 string?

January 12th, 2017 No comments

C++ 不是号称不限制你的开发方式么,每个库想怎么搞就怎么搞,这明明就是 C++的优势,不知道大家抱怨个啥?哈哈

接着说 std::string 的性能问题,举个具体例子吧,之前接手过一个项目,别的部门同事自己撸的一套 DirectUI 系统,用 tinyxml 解析界面节点,项目简单的时候没啥,随着ui越来越复杂,数千个节点,每个xml节点若干属性,每个属性就是一个字符串,我记得好像有500+ KB的 xml要解析,而且这部分界面还没法延迟初始化,必须启动加载时做完,启动十分慢。profile下来,很多时间卡在 tinyxml上,整个过程接近 3秒,费时最前的操作卡在处理各种字符串的操作上。

把 tinyxml 换成其他 xml库 ?没那么容易,项目各处模块都在依赖 tinyxml的各种接口和类。一开始觉得内部的 TiXmlString 实现有问题,换成 std::string,vc 2012下时间从3秒增加到4秒,更不靠谱(vs2012应该已经有所谓SSO了),所以人家 tinyxml 这里用自己的 TiXmlString 肯定也是比较过的,不然干嘛不用 std::string 。

Read more…

Categories: 编程技术 Tags:

什么时候用C而不用C++?

June 16th, 2015 No comments

知乎问题《什么时候用C而不用C++?》:

前两天不是有一个问题是“什么时候用C++而不用C”,我一直觉得问错了,难道不是“能用C++就不用C”么?那么当然就要讨论什么时候用C而不用C++啦。

一直以来都严格遵循OO的原则来进行开发(用的工具是C#和Qt),直到最近,开始接手某同事的代码,整个项目20多个小工程(代码量并不多),除了界面部分用了MFC这种不伦不类的OO以外,所有的代码都是C写的。但是模块化做的非常好。后来跟他讨论为何不用C++,他说其实没有什么特别的,就是习惯和爱好而已,后又补充:

如果不用多态的话,其实不管怎么写,不管用那种语言写,都算不上真正的OO

忽然觉得很有道理……

其实这是一个好问题,

题主开始欣赏到纯 C代码所带来的 “美感” 了,即简单性和可拆分性。代码是自底向上构造,一个模块只做好一个模块的事情,任意拆分组合。对于有参考的 OOP系统建模,自顶向下的构造代码抽象方法是有效率的,是方便的,对于新领域,没有任何参考时,刻意抽象会带来额外负担,并进一步增加系统耦合性,设计调整,往往需要大面积修改代码。

有兴趣你可以读读《Unix编程艺术》,OOP的思维模式,是大一统的;C的思维模式,是分离的。前者方便但容易造成高耦合,后者灵活但开发开发太累。用 C开发,应该刻意强调 “简单” 和 “可拆分”。一个个象搭积木一样的把基础系统搭建出来,哪个模块出问题,局部替换即可。

自底向上的开发模式,并不是从不站在大局考虑问题,而是从某个子系统具体实现开始,从局部迭代,逐步反思全局设计,刻意保持低偶合,一个模块一个模块的来,再逐步尝试组合。

自底向上强调先有实践,再总结理论,理论反过来指导实践,又从实践中迭代修正理论。这和人类认识世界的顺序是一样的,先捕猎筑巢,反思自然是怎么回事,又发现可以生火,又思考自然到底怎么回事情。

它的反面,是指大一统设计,你一开始用 UML画出整套系统的类结构,然后再开工设计。这种思维习惯,如果是参考已有系统做一个类似的设计,问题不大,全新设计的话,他总有一个前提,就是 “你能完整认识整个大自然”,就像人类一开始就要认识捕猎和筑巢还有取火一样。否则每次对世界有了新认识,OOP的自顶向下设计方法都能给你带来巨大的负担。

所以有些人才会说:OOP设计习惯会依赖一系列设计灵巧的 BaseObject,然而过段时间后再来看你的项目,当其中某个基础抽象类出现问题是,往往面临大范围的代码调整。这其实就是他们使用自顶向下思维方法,在逐步进入新世界时候,所带来的困惑。

当然也有人批判这种强调简单性和可拆分性的 Unix思维。认为世界不是总能保持简单和可拆分的,他们之间是有各种千丝万缕联系的,你一味的保持简单性和可拆分性,你会让别人很累。这里给你个药方,底层系统,基础组建,尽量用 C的方法,很好的设计成模块,随着你编程的积累,这些模块象积木一样越来越多,而彼此都无太大关系,甚至不少 .c文件都能独立运行,并没有一个一统天下的 common.h让大家去 include,接口其他语言也方便。

然后在你做到具体应用时根据不同的需求,用C++或者其他语言,将他们象胶水一样粘合起来。这时候,再把你的 common.h,写到你的 C++或者其他语言里面去。当然,作为胶水的语言不一定非要是 C++了,也可以是其他语言。
————-
PS: 这里主要在探讨 OOP存在的问题,并没有讨论嵌入式这种资源限制的情况,以及操作系统和底层等需要精确控制硬件和内存的情况,更没有讨论 C++在语言设计层面的事情。

————-

转部分答疑:(点击more展开)

Read more…

Categories: 编译原理, 随笔 Tags:

C++的反思

June 16th, 2015 62 comments

最近两年 C++又有很多人出来追捧,并且追捧者充满了各种优越感,似乎不写 C++你就一辈子是低端程序员了,面对这种现象,要不要出来适时的黑一下 C++呢?呵呵呵。

咱们要有点娱乐精神,关于 C++的笑话数都数不清:

笑话:C++是一门不吉祥的语言,据说波音公司之前用ADA为飞机硬件编程,一直用的好好的,后来招聘了一伙大学生,学生们说我靠还在用这么落后的语言,然后换成C++重构后飞机就坠毁了。

笑话:什么是C++程序员呢?就是本来10行写得完的程序,他非要用30行来完成,并自称“封装”,但每每到第二个项目的时候却将80%打破重写,并美其名曰 “重构”。

笑话:C容易擦枪走火打到自己的脚,用C++虽然不容易,但一旦走火,就会把你整条腿给炸飞了。

笑话:同时学习两年 Java的程序员在一起讨论的是面向对象和设计模式,而同时学习两年 C++的程序员,在一起讨论的是 template和各种语言规范到底怎么回事情。

笑话:教别人学 C++的人都挣大钱了,而很多真正用 C++的人,都死的很惨。

笑话:C++有太多地方可以让一个人表现自己“很聪明”,所以使用C++越久的人,约觉得自己“很聪明”结果步入陷阱都不知道,掉坑里了还觉得估计是自己没学好 C++。

笑话:好多写了十多年 C++程序的人,至今说不清楚 C++到底有多少规范,至今仍然时不时的落入某些坑中。

笑话:很多认为 C++方便跨平台的人,实际编写跨平台代码时,都会发现自己难找到两个支持相同标准的 C++编译器。
—————

Q:那 C++为什么还能看到那么多粉丝呢?
A:其实是因为 Windows,因为 Windows的兴起带动了 C++,C++本来就是一门只适合开发 GUI的语言。

Q:为何 C++只适合开发 GUI呢?
A:你看 Unix下没有 GUI,为啥清一色的 C呀?所有的系统级问题都能在 C里找到成熟的解决方案,应用级问题都能用其他高级语言很好地解决,哪里有 C++什么事情呀?

Q:你强词夺理,Unix下也有 C++的项目呀。
A:有,没错,你任然可以用任何语言编写任何糟糕的代码。

Q:别瞎扯了,你都在说些什么?连C++和 Windows 都扯到一起去了。
A:回想下当年的情景,一个大牛在教一群初学者如何编程。一边开发一边指着屏幕上说,你看,这是一个 Button,我们可以用一个对象来描述它,那是一个 panel我们也可以用一个对象来描述它,并且你们有没有发现,其实 Button和 Panel是有血缘关系的,你们看。。。这样就出来了。。。。下面的学生以前都是学着学校落后的教材,有些甚至还在用 turboc的 bgi库来画一些点和圆。哪里见过这么这么华丽的 Windows 界面呀。大牛说的话,象金科玉律一样的铭刻在自己幼小的心理。一边学着 Windows,一边发现,果然,他们都需要一个基类,果然,他们是兄弟关系,共同包含一些基本属性,可以放到基类去。他们越用越爽,潜意识里觉得因为 C++这么顺利的帮他们解决那么多界面问题,那看来 C++可以帮他们解决一切问题了。于是开发完界面以后,他们继续开发,当他们碰到各种设计问题时,反而认为肯定自己没有用好 C++。于是强迫自己用下去,然后就完蛋了。

(点击 more展开)

Read more…

Categories: 编程技术, 随笔 Tags:

精通 C++ 是一种怎样的体验?

June 3rd, 2015 3 comments

没什么用,精通C++不代表能写出好程序,就像知道回字有四种写法照样无法写出好文章来。不要把精力浪费太多具体某语言上,不管你搞网络,还是搞数据库,搞数字信号处理还是搞人工智能,或者和李开复一样搞语音识别,你会发现,功夫都在语言之外。

花太多时间学C++一点用都没有,不如打牢基础然后具体去学习各种知识,或者直接进行一些具体实践性的开发。所以我看简历,只会注意他具体做了什么,解决哪些问题,取得何种成绩。精通或者熟悉C++基本都是当垃圾信息过滤掉的,如果你简历上最耀眼的只是熟悉某语言,那和垃圾简历没区别。

所以,不要雇佣号称精通C++的人就是这个理由。

其实最精通中文的的人是各种语言学家,大学里专门研究中文的人,哪个字的出处,哪个用词正确与否,那个生僻字怎么念都了然于胸。so what ?能代表他们就能出口成章,提笔成文么?

就像《三体》写得好,是因为大刘在科学在剧情构思上的知识牛逼,而不是大刘会咬文嚼字。Kaiser 在知乎上谈笑风声,因为他历史知识丰富,《史记》《汉书》《三国志》信手拈来,外加观点独到,幽默风趣,从来不是因为他知道回字有四种写法,或者八种写法。

我们说 Fabrice牛逼,因为他对 数学,信号处理,计算机体系等三个方面有着深刻的认识,从而他能做出 ffmpeg, qemu, tinycc 这样的项目来,从而他算 pi可以算到世界第一快,所以大家觉得很牛逼,这并不是因为听说他 C++有多牛。

所以看到简历上如果没什么值得称道的东西,只有一个 “精通C++”,在用人公司眼里就和一个笑话差不多。


补充, @欧阳婕 网友提到的陆游诗,

《示子遹》
——陆游
  我初学诗日,但欲工藻绘;
  中年始少悟,渐若窥宏大。
  怪奇亦间出,如石漱湍濑。
  数仞李杜墙,常恨欠领会。
  元白才倚门,温李真自郐。
  正令笔扛鼎,亦未造三昧。
  诗为六艺一,岂用资狡狯?
  汝果欲学诗,工夫在诗外。

注意第一句,“我刚学诗,只想精通辞藻” 就是这个所谓 “精通C++” 的状态

Categories: 编程技术 Tags:
Wordpress Social Share Plugin powered by Ultimatelysocial