Posted on 2015-01-26 14:58:26 c
摘要:协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。协程可以在运行期间的某个点上暂停执行,并在恢复运行时从暂停的点上继续执行。 协程已经被证明是一种非常有用的程序组件,不仅被python、lua、ruby等脚本语言广泛采用,而且被新一代面向多核的编程语言如golang rust-lang等采用作为并发的基本单位。 协程可以被认为是一种用户空间线程,与传统的线程相比,有2个主要的优点:
与线程不同,协程是自己主动让出CPU,并交付他期望的下一个协程运行,而不是在任何时候都有可能被系统调度打断。因此协程的使用更加清晰易懂,并且多数情况下不需要锁机制。 与线程相比,协程的切换由程序控制,发生在用户空间而非内核空间,因此切换的代价非常小。
协程可以认为是一种用户态的线程,与系统提供的线程不同点是,它需要主动让出CPU时间,而不是由系统进行调度,即控制权在程序员手上。既然看成是用户态线程,那必然要求程序员自己进行各个协程的调度,这样就必须提供一种机制供编写协程的人将当前协程挂起,即保存协程运行场景的一些数据,调度器在其他协程挂起时再将此协程运行场景的数据恢复,以便继续运行。这里我们将协程运行场景的数据称为上下文。
阅读全文Posted on 2015-01-25 18:37:38 c
对一个应用程序员来讲,了解汇编不是必需的,更少有手写纯汇编的需求。但是如果能了解些基本的汇编知识,对程序调试和一些语言特性的理解是大有裨益的。本文介绍 AT&T 语法的汇编的要点以及 GCC 使用的内联汇编(inline assembly)的使用。
AT&T 汇编是 GCC 所采用的语法,要点:
通用寄存器(x86_64):
X86_64 下 ABI 调用约定:
内联汇编允许在 C/C++ 代码中嵌入汇编代码,以优化关键代码或者使用架构特有的指令。内联汇编的基本格式如下:
asm [volatile] ( <assembler template>
: ["constraints"(var)] [,"constraints"(var)] /* output operands */
: ["constraints"(var)] [,"constraints"(var)] /* input operands */
: ["register"] [,"register"] [,"memory"] /* clobbered registers */
);
中括号中为可选部分,尖括号为必选部分。圆括号内由 ‘:’ 分割为四个部分:
常用的 constraints 为:
输出 constraints 中需要下面至少一个『修饰符』(constraints modifier)作为前缀:
下面看几个示例:
asm ("":::); //~ nothing
asm ("incl %%eax\n\t":::"eax"); //~ access register directly
asm ("movq $1, %0\n\t" : "=m"(var)); //~ write 1 to var
asm ("mov %0, %%eax\n\t" : : "m"(var)); //~ read from var to eax
//~ read a to eax, read b to either ebx|ecx|edx|edi|esi, add it to eax, write back eax to a
asm ("addl %1, %0\n\t" : "+a"(a) : "r"(b));
asm ("incq global_var\n\t" :::"memory"); //~ access global_var directly
asm ("incl %0\n\t" : "+q"(var)); //~ read var to either eax|ebx|ecx|edx, increase it, write it back to var
asm ("incl %0\n\t" : "=q"(var) : "0"(var)) //~ the same as above, constraint 0 means using the same register
asm ("incl %[__var__]\n\t" : [__var__]"+q"(var)); //~ use user-defined placeholder
最后一个示例使用了用户自定义的占位符,通常在输入输入变量较多的情况下使用,省得逐个地对应。
在汇编中调用 printf:
#include <stdio.h>
int
main()
{
char *fmt = "Hello, %s\n";
char *s = "World";
int ret = 0;
asm (" callq printf\n\t"
: "=a"(ret)
: "D"(fmt), "S"(s));
printf("ret: %d\n", ret);
return 0;
}
在汇编中进行系统调用:
int
sys_write(int fd, const char *buf, size_t n)
{
int ret;
asm (
"syscall\n\t"
: "=a"(ret)
: "0"(1), "D"(fd), "S"(buf), "d"(n)
);
return ret;
}
int
main()
{
char *s = "Hello, World\n";
printf("%d\n", sys_write(fileno(stdout), s, strlen(s)));
return 0;
}
Posted on 2014-02-12 07:36:22 c
摘要:libev是Marc Lehmann用C写的高性能事件循环库。通过libev,可以灵活地把各种事件组织管理起来,如:时钟、io、信号等。libev在业界内也是广受好评,不少项目都采用它来做底层的事件循环。
阅读全文Posted on 2014-02-10 09:30:13 c
摘要:每个文件描述符都有一个close-on-exec标志。默认情况下,这个标志最后一位被设置为 0。这个标志符的具体作用在于当开辟其他进程调用exec()族函数时,在调用exec函数之前为exec族函数释放对应的文件描述符。
阅读全文