05 2012 档案
摘要:同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,有人认为asynchronous IO和non-blocking IO是一个东西。这其实是因为不同的人的知识背景不同,并且在讨论这个问题的时候上下文(context)也不相同。所以,为了更好的回答这个问题,我先限定一下本文的上下文。本文讨论的背景是Linux环境下的network IO。本文最重要的参考文献是Richard Stevens的“UNIX® Network
阅读全文
摘要:结合阻塞与非阻塞访问、poll 函数可以较好地解决设备的读写,但是如果有了异步通知就更方便了。异步通知的意思是:一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,这一点非常类似于硬件上“中断”地概念,比较准确的称谓是:信号驱动(SIGIO)的异步 I/O。可以使用signal()函数来设置对应的信号的处理函数。函数原型是:void (*signal(int signo,void (*func)(int))) (int)我们先来看一个使用信号驱动的例子,通过signal(SIGIO,input_handler) 对打开的文件fd 启动信号机制,输入可获得时inputhand
阅读全文
摘要:首先再来提一下I/O多路转接的基本思想:先构造一张有关描述符的表,然后调用一个函数,它要到这些描述符中的一个已准备好进行 I/O时才返回。在返回时,它告诉进程哪一个描述符已准备好可以进行 I/O。select函数的参数将告诉内核:(1) 我们所关心的描述符。(2) 对于每个描述符我们所关心的条件(是否读一个给定的描述符?是否想写一个给定的描述符?是否关心一个描述符的异常条件?)。(3) 希望等待多长时间(可以永远等待,等待一个固定量时间,或完全不等待)select从内核返回后内核会告诉我们:(1) 已准备好的描述符的数量。(2) 哪一个描述符已准备好读、写或异常条件。select 用于查询设备
阅读全文
摘要:I/O多路转接至今还不是 POSIX的组成部分。SVR4和 4.3 + BSD都提供select函数以执行I/O多路转接。poll函数只由SVR4 提供。SVR4 实际上用poll实现select。I/O多路转接的基本思想是:先构造一张有关描述符的表,然后调用一个函数,它要到这些描述符中的一个已准备好进行 I/O时才返回。在返回时,它告诉进程哪一个描述符已准备好可以进行 I/O。I/O多路转接在服务器端用的比较多,可以同时处理多个连接的接入,但是也有缺陷,貌似只能接受1024个接入,因此现在又了epoll,当然这不是讨论的重点了。select的函数原型为:int select(int numf
阅读全文
摘要:用户程序需要系统提供服务的时候,会通过系统调用产生一个int 0x80的软中断,就会进入到系统调用的入口函数,入口函数存放在以下文件当中:以下是系统调用的入口:(arch/x86/kernel/entry_32.S)http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/arch/x86/kernel/entry_32.S517 ENTRY(system_call)518 RING0_INT_FRAME # can't unwind into user space anyway519...
阅读全文
摘要:死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。死锁要产生必须具备四个必要条件:1. 互斥条件 2. 请求和保持条件 3.不可剥夺条件 4. 环路等待条件。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。一下举一个Linux环境下产生死锁的程序(首先是驱动部分):#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <as
阅读全文
摘要:在编写Linux内核驱动程序的时候,如果不动态生成设备号的话,需要自己手动分配设备号,有可能你分配的设备号会与已有设备号相同而产生冲突。因此推荐自动分配设备号。使用下面的函数:int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)该函数需要传递给它指定的第一个次设备号baseminor(一般为0)和要分配的设备数count,以及设备名,调用该函数后自动分配得到的设备号保存在dev中。当使用了alloc_chrdev_region()动态分配设备号之后,需要依次使用...
阅读全文
摘要:/*基本思想就是将所有结点分成两个集合,一个是st所在的集合,另一个是st不在的集合,每次从不包含st的集合中找出一个最优的结点加入到st所在的集合,并更新st到所有不在其所在集合中的点的距离。使用一个visit[]数组来标识结点在哪一个集合中。使用dist[]数组来记录st结点到其他结点的最短路径。*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;int const MAXN = 1000;const int INF = 1000000000;int g[
阅读全文
摘要:我使用的是Visual Studio 11 beta,Win7系统。下面示例程序中通过使用_CrtDumpMemoryLeaks() 或 _CrtSetDbgFlag()来进行内存泄露检测。当发生内存泄露的时候在debug窗口会给出内存泄露的信息,其中_CrtDumpMemoryLeaks用来需要检测的代码的后面,_CrtSetDbgFlag() 用在程序的一开始,总的来说_CrtSetDbgFlag() 比较强大一点。在程序的开头最好加上以下宏定义:#ifdef _DEBUG#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)#endif这样在
阅读全文
摘要:链表合并先,将两个链表排序,在合并的时候引入一个内存泄露的问题,之后会继续讨论。#include <ctime>#include <cstdlib>#include <iostream>#include <cstdio>using namespace std;#define NN#define RANGE 100#define NUM 10struct node{int value;node * next;node(int v = -1, node *nxt = NULL) : value(v),next(nxt){}};node * make_
阅读全文
摘要:就直接贴代码了:#include <iostream>#include <ctime>#include <cstdlib>using namespace std;#define NN 1struct node{int value;node * next;node(int v = -1, node *nxt = NULL) : value(v),next(nxt){}};node* reverse(node * ); //直接使用 node 代表这个结构体node * make_link();void display(node *);int main(){no
阅读全文
摘要:C++用 ifstream 声明输入文件对象,用 ofstream 声明输出文件对象。getline的使用:(感觉有点像孔乙己的茴香豆的 茴 的写法了)#include<iostream>#include<fstream>#include<string>using namespace std;int main(){ ifstream infile("getline.txt",ios::in | ios::binary); char buf1_1[30]; string buf1; char buf2[30]; ///注意这里getline
阅读全文
摘要:Linux环境下:/**struct timeval { time_t tv_sec; // 秒 suseconds_t tv_usec; // 微妙 (10的负六次方)}; typedef struct timespec{time_t tv_sec;//秒long tv_nsex;//纳秒}timespec_t;**/#include <algorithm>#include <vector>#include <stdio.h>#include <stdlib.h>#include <sys/time.h>double getTime
阅读全文
摘要:今天在QQ群中有人问起这两个问题,我只是在oneNote中做过笔记,也不是很熟,只不过oneNote的搜索功能太难用了。觉得这些基本功问题还是要熟悉才好。首先是格式转换,什么浮点数转换为字符串,字符串转换为浮点数,建议使用C++ 的字符处理类,stringstream,在exceptional C++中好像说过sprintf什么的不是很安全。下面来看例子:#include <sstream>#include <iostream>using namespace std;int main() stringstream ss; double a = 3.141592; dou
阅读全文
摘要:原文地址:http://coolshell.cn/articles/3643.html想更深入的学习GDB调试程序可以学习陈皓老师的:用GDB调试程序七、八年前写过一篇《用GDB调试程序》,于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题。这么多年来,有一些问题是大家反复在问的,一方面,我觉得我以前的文章可能没有说清楚,另一方面,我觉得大家常问的问题正是最有用的,所以,在这里罗列出来。希望大家补充。一、多线程调试多线程调试可能是问得最多的。其实,重要就是下面几个命令:info thread 查看当前进程的线程。 thread <
阅读全文
摘要:一:列文件清单1. List(gdb) list line1,line2二:执行程序要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。(gdb)set args –b –x(gdb) show argsbacktrace命令为堆栈提供向后跟踪功能。Backtrace 命令产生一张
阅读全文
摘要:接上一篇:使用 GNU 的 GDB调试器,内存布局和栈 —— 01原文地址:http://www.dirac.org/linux/gdb/02a-Memory_Layout_And_The_Stack.php符号表 一个符号就是一个变量或者一个函数。符号表如你所想:就是在可执行文件中的一个包含变量和函数的表。 正常情况下符号表只包含符号的地址,因为计算机不使用我们给变量或者函数起的名字。 为了让GDB对我们来说有用,有必要能够通过变量或者函数名来引用变量,而不是使用它们的地址。人类使用的是诸如“main()”或者“i”。 计算机使用如0x804b64d 或0xbffff784 之类的地址。因为
阅读全文
摘要:使用 GNU 的 GDB调试器,内存布局和栈原文地址:http://www.dirac.org/linux/gdb/02a-Memory_Layout_And_The_Stack.php我们会学些什么? 为了更高效的学习使用GDB,你必须了解帧,通常也成为栈帧,因为帧构成了栈。为了学习栈,我们需要了解可执行文件的内存布局。这里的讨论主要都是理论上的,但是为了使学习比较有趣,在本章结束之前我们将通过GDB来展现栈和栈帧的例子。 本章学习的东西似乎相当的理论化,但是对于达到以下目的来说却是非常有用的:1. 理解栈对于使用GDB调试器是绝对有必要的2. 了解一个进程的内存布局有助于我们理解什么是段错
阅读全文
摘要:#include <algorithm>#include <vector>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <windows.h>using namespace std;#define SIZE 1024 * 1024 * 1024int main(){LARGE_INTEGER start; LARGE_INTEGER end; LARGE_INTEGER freq; QueryPerformanceFrequency(&
阅读全文
摘要:#include<stdio.h>int main(){ int b = 3; int arr[] = {6,7,8,9,10}; int *ptr = arr; *(ptr++) += 123; //printf("%d,%d\n", *ptr, *(++ptr)); //输出:8,8 printf("%d,%d\n", *ptr, *(ptr++));//输出:8,7 return 0;}_cdecl 压栈方式是从右到左更加明显的例子:#include<stdio.h>int main(){ int a = 5, b = 7;
阅读全文
摘要:系统调用接口往往是通过中断来实现,比如Linux使用0x80号中断作为系统调用的入口,Windows采用0x2E号中断作为系统调用的入口。EAX名字C语言定义含义参数1exitvoid _exit(int status)退出进程EBX表示退出码2forkpid_t fork(void)复制进程EBX表示复制参数3readssize_t read( int fd,void *buf,size_t count)读文件EBX表示文件句柄,ECX表示读取缓冲地址,EDX表示读取的大小4writessize_t write( int fd,const void *buf,size_t count);写.
阅读全文
摘要:程序从main开始的吗?在执行main之前全局变量已经初始化,main函数的两个参数也被正确传了进来,堆和栈的初始化也已经完成,一些系统I/O也被初始化。完成上面这些工作的函数称为入口函数(Entry Point)。一个典型的运行步骤大致如下:·操作系统在创建进程后,把控制权交到了程序的入口,这个入口往往是运行库中的某个函数。·入口函数对运行库和程序运行环境进行初始化,包括堆、I/O、线程、全局变量构造等。·入口函数在完成初始化之后,调用main函数,正是开始执行程序主体部分·main函数执行完毕以后,返回到入口函数,入口函数进行清理工作,包括全局变量的
阅读全文
摘要:注:这一章的内容比较经典,之前看“深入理解计算机系统”的时候,也有看到栈帧(Stack Frame),但是不是很清楚,通过这一章的讲解,更清楚了。如果能再结合讲讲GDB调试的话就更完美了。栈:栈用于维护函数调用的上下文,离开了站函数调用就没法实现。堆:堆是用来容纳应用程序动态分配的内存区域,当程序使用malloc或new分配内存时,得到的内存来自堆里。Linux进程地址空间内存布局:在操作系统中,栈总是向下增长的。在i386下,栈顶由称为esp的寄存器进行定位。压栈的操作使栈顶的地址减小,弹出的操作使栈顶的地址增大。 程序栈实例在栈底的地址是0xbfffffff,而esp寄存器表明了栈顶,地址
阅读全文
摘要:第八章不是很感兴趣,直接跳到第九章。 DLL即动态链接库(Dynamic Link Library)的缩写. 一个DLL中有两个数据段,一个进程间共享,另一个私有. 当我们使用“__declspec(dllexport)”时表示该符号是从本DLL导出的符号。“__declspec(dllimport)”表示该符号是从别的DLL导入的符号。创建DLL:/*math.c*/__declspec(dllexport) double Add(double a, double b){return a+b;}__declspec(dllexport) double Sub(double a, doub..
阅读全文
摘要:静态链接浪费内存和磁盘空间、模块更新困难等问题,因此寻找一种更好的办法来组织程序模块。 静态链接对程序的更新、部署和发布也会带来很多麻烦。动态链接: 就是不对那些组成程序的目标文件进行链接,等到程序要运行时才进行链接。动态链接的方式使得开发过程中各个模块更加独立、耦合度更小,便于不同的开发者和开发组织之间进行独立的开发和测试。动态链接还有一个特点就是程序在运行时可以动态的选择加载各种程序模块,使得插件成为可能。Linux系统中,ELF动态链接文件被称为动态共享对象(DSO,Dynamic Shared Objects),简称共享对象,它们一般都是以“.so”为扩展名;动态链接文件被称为动态..
阅读全文
摘要:由 user process角度来说明的话,VMA 是 user process 里一段 virtual address space 区域;virtual address space 是连续的内存空间,当然VMA 也会是连续的空间。VMA对 Linux 的主要好处是,可以内存的使用更有效率,並且更容易管理 user process address space。从另一个观念来看,VMA 可以让 Linux kernel 以 process 的角度来管理 virtual address space。Process 的 VMA对应,可以由 /proc/<pid>/maps 来查看;例如
阅读全文
摘要:进程与程序: 程序是一个静态的概念,它就是这些预编译好的指令和数据集合的一个文件;进程则是一个动态的概念,它是程序运行时的一个过程,很多时候把动态库叫做运行时也有一定的含义。 一般来来说,C语言指针大小的位数与虚拟空间的位数相同,如果32位平台下指针为32位,即4字节;64位平台下的指针为64位,即8字节。Intel自从1995年的Pentium Pro CPU开始采用了36位的物理地址,也就是可以访问高达64GB的物理内存。Intel把这个地址扩展方式叫做PAE(Physical Address Extension)。应用程序如何使用这些大于常规内存的空间?一个很常见的方法就是操作系统提供一
阅读全文
摘要:前一篇寻找第k小的数可以用来处理大量数据,这里介绍的堆排序也可以用来处理大量数据的情况,而且堆排序的思想还可以找出前k小的数据(自然也可以找出前k大的数据,就看是建立大根或者小根堆了),只需要建立k个数据的堆就行了,然后依次把后面的数据放入到堆中的适当位置。这里只是实现了堆排序(并没有实现找出前k小的数)。#include <iostream>#include <algorithm>#include <ctime>#include <cstdlib>#include <iterator>using namespace std;cons
阅读全文
摘要:使用快排中的partition方法,可以很快找到一个无序序列中的第k小的数。思想:对于一个数组a[0...n-1],分段成a[0...st-1],a[s],a[st+1...n-1]分组后,a[0...st-1]里面的元素都小于等于a[st],a[st+1...n-1]里面的元素都大于等于a[st]. 所以,如果 st==k-1,那么a[st]就是要求的数。如果 st>k-1,那么要求的数在a[0...st-1]里。 如果 st<k-1,那么要求的数在a[st+1...n-1]里。因此我们把范围缩小到 a[0...st-1]或者a[st+1...n-1]里,然后对缩小范围后的数组也
阅读全文
摘要:#include <iostream>#include <algorithm>#include <cstdio>#include <cstdlib>#include <ctime>using namespace std;const int NUM = 25;/** 这里默认使用的pivot是a[left] partition将 a[]分成两部分,左边的部分小于pivot,右边的部分大于pivot**////两种partition方式都是对的/*int partition(int a[],int left, int right) //分
阅读全文
摘要:1. 下面我想就管理中的组织结构这个问题谈谈个人粗浅的看法.要点: "粗浅的"这个一般不翻译全句可翻译为: I would like to put forward my own opinion about organizing in management.2. 为了让人们能够更好的合作,必须明确他们的任务、目标、责任与权力。要点:必须明确的内容,可以用两种方式翻译全句可翻译为:In order for people to cooperate effectively, they must know their roles, their objectives, their re
阅读全文
摘要:cl的位置:开始 –> 所有程序 -> Microsoft Visual Studio ->Visual Studio Tools -> Developer Command Prompt编译器产生通用对象文件格式 (COFF) 对象 (.obj) 文件。链接器产生可执行文件 (.exe) 或动态链接库文件 (DLL)。注意,所有编译器选项都区分大小写。若要编译但不链接,请使用/c。语法:CL [option...] file... [option | file]... [lib...] [@command-file] [/link link-opt...]选项optio
阅读全文
摘要:PE: Portable ExecutableCOFF: Common Object File Format跟ELF一样,PE中也允许程序员将变量后函数放到自定义段。在GCC中使用“__attribute__((section)("name"))”,在VISUAL C++中可以使用 “#pragma”编译器指示。#pragma data_seg("FOO")int global = 1;#pragma data_seg(".data")使用cl 编译器:开始 –> 所有程序 -> Microsoft Visual Stud
阅读全文
摘要:对于多个输入目标文件,链接器如何将它们的各个段合并到输出文件? 或者说,输出文件中的空间如何分配给输入文件?/*假设有a.c*/extern int sharedint main(){int a = 100;swap(&a,&shared);}/*b.c*/int shared = 1;void swap(int *a, int *b){*a ^= *b ^= *a ^= *b;}“链接器为目标文件分配地址和空间”中的“地址和空间”其实有两个含义:第一个是在输出的可执行文件中的空间;第二个是在装载后的虚拟地址中的虚拟地址空间。这个链接过程分两步:第一步 : 空间与地址分配扫描所
阅读全文
摘要:GAS中每个操作都是有一个字符的后缀,表明操作数的大小。C声明GAS后缀大小(字节)charb1shortw2(unsigned) int / long / char*l4floats4doublel8long doublet10/12注意:GAL使用后缀“l”同时表示4字节整数和8字节双精度浮点数,这不会产生歧义因为浮点数使用的是完全不同的指令和寄存器。操作数格式:格式操作数值名称样例(GAS = C语言)$ImmImm立即数寻址$1 = 1EaR[Ea]寄存器寻址%eax = eaxImmM[Imm]绝对寻址0x104 = *0x104(Ea)M[R[Ea]]间接寻址(%eax)= *ea
阅读全文
摘要:最近在看“程序员的自我修养”,看到了gcc内嵌汇编,静态链接那章的示例程序比较有趣,于是准备学习一下AT&T语法的gcc内嵌汇编。以前学微机原理的时候学习过汇编,现在基本上还给了老师,还是复习一下吧。像大家一样先来介绍一下AT&T语法与Intel asm语法的不同(顺便也学学基本知识):在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如:AT&T 格式Intel 格式pushl %eaxpush eax在 AT&T 汇编格式中,用 '$' 前缀表示一个立即操
阅读全文
摘要:之前上嵌入式的课程,罗老师强调了函数可重入的重要性,而且还举例某某著名通信公司开发过程中函数不可重入导致的问题,于是对函数可不可重入比较注意,在看书的时候又遇到了这个问题,于是准备认真学习一下。一、可重入函数1)什么是可重入性?可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反,不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。2)可重入函数:不为.
阅读全文