博文

什么是DMA(2007-11-04 15:20:00)

摘要:当我们向计算机中加入了一块新的声卡或其它适配卡时,安装程序可能会提醒我们应该选择一个DMA通道。那DMA是什么呢? DMA(Direct Memory Access),即直接存储器存取,是一种快速传送数据的机制。数据传递可以从适配卡到内存,从内存到适配卡或从一段内存到另一段内存。DMA技术的重要性在于,利用它进行数据传送时不需要CPU的参与。每台电脑主机板上都有DMA控制器,通常计算机对其编程,并用一个适配器上的ROM(如软盘驱动控制器上的ROM)来储存程序,这些程序控制DMA传送数据。一旦控制器初始化完成,数据开始传送,DMA就可以脱离CPU,独立完成数据传送。     在DMA传送开始的短暂时间内,基本上有两个处理器为它工作,一个执行程序代码,一个传送数据。利用DMA传送数据的另一个好处是,数据直接在源地址和目的地址之间传送,不需要中间媒介。如果通过CPU把一个字节从适配卡传送至内存,需要两步操作。首先,CPU把这个字节从适配卡读到内部寄存器中,然后再从寄存器传送到内存的适当地址。DMA控制器将这些操作简化为一步,它操作总线上的控制信号,使写字节一次完成。这样大大提高了计算机运行速度和工作效率。     计算机发展到今天,DMA已不再用于内存到内存的数据传送,因为CPU速度非常快,做这件事,比用DMA控制还要快,但要在适配卡和内存之间传送数据,仍然是非DMA莫属。要从适配卡到内存传送数据,DMA同时触发从适配卡读数据总线(即I/O读操作)和向内存写数据的总线。激活I/O读操作就是让适配卡把一个数据单位(通常是一个字节或一个字)放到PC数据总线上,因为此时内存写总线也被激活,数据就被同时从PC总线上拷贝到内存中。      对于每一次写操作,DMA控制器都控制地址总线,通知应将数据写到哪段内存中去。 DMA控制数据从内存传送到适配卡的方法与上面类似。对每一个要传送的单位数据,DMA控制器激活读内存和I/O写操作的总线。内存地址被放到地址总线上,像从适配卡到内存传送数据一样,以数据总线为通道,数据从源地址直接传送到目的地址。 DMA从DMA请求线(DREQ)上接收DMA请求,正像中断控制器从中断请求线(IRQ)上接收中断请求一样。&nbs......

阅读全文(3094) | 评论:1

IRQ(2007-11-04 15:16:00)

摘要:IRQ 为 Interrupt ReQuest的缩写,中文可译为中断请求。因为计算机中每个组成组件都会拥有一个独立的IRQ,除了使用PCI总线的PCI卡之外,每一组件都会单独占用一个 IRQ,且不能重复使用。 由于在计算机运行中,CPU是持续处于忙碌状态,而当硬件接口设备开始或结束收发信息,需要CPU处理信息运算时,便会透过IRQ对CPU送出中断请求讯号,让CPU储存正在进行的工作,然后暂停手边的工作,先行处理周边硬件提出的需求,这便是中断请求的作用。 在每个系统中会有两颗芯片来提供16个IRQ,其中大多的IRQ都有固定的编排,例如 IRQ 0固定为系统定时器,IRQ 1则是键盘。因为每一个IRQ只能让一种设备使用,所以IRQ数目十分有限,若计算机安装很多的配件,IRQ势必就会不敷使用,所以可能会发生两个设备共占同一个IRQ的现象,此时也就会出现IRQ冲突问题,造成该设备无法使用。 最简单的解决方法就是到操作系统的硬件设备管理器中去手动调整IRQ的分配,或是在BIOS中作调整。如果是IRQ不敷使用的情形,可以利用其它的方式来解决此一窘境,像是PCI总线可以共享一个IRQ,所以基本上可以采增加PCI插卡的方式,就不会被IRQ 所限制。其次是使用USB传输来解决,因为USB控制芯片只会占用一个IRQ,并非所有的USB产品都要独占一个IRQ,所以理论上可以连结最多到127件周边产品,而且目前拥有USB传输界面的产品也越来越普遍了。所以对于传输速度要求不高的周边设备,未来大概将逐渐朝USB接口发展。......

阅读全文(9389) | 评论:2

中断解析(2007-10-01 16:53:00)

摘要:中断解析 一、中断是什么 中断的汉语解释是半中间发生阻隔、停顿或故障而断开。那么,在计算机系统中,我们为什么需要“阻隔、停顿和断开”呢? 举个日常生活中的例子,比如说我正在厨房用煤气烧一壶水,这样就只能守在厨房里,苦苦等着水开——如果水溢出来浇灭了煤气,有可能就要发生一场灾难了。等啊等啊,外边突然传来了惊奇的叫声“怎么不关水龙头?”于是我惭愧的发现,刚才接水之后只顾着抱怨这份无聊的差事,居然忘了这事,于是慌慌张张的冲向水管,三下两下关了龙头,声音又传到耳边,“怎么干什么都是这么马虎?”。伸伸舌头,这件小事就这么过去了,我落寞的眼神又落在了水壶上。 门外忽然又传来了铿锵有力的歌声,我最喜欢的古装剧要开演了,真想夺门而出,然而,听着水壶发出“咕嘟咕嘟”的声音,我清楚:除非等到水开,否则没有我享受人生的时候。   这个场景跟中断有什么关系呢?   如果说我专心致志等待水开是一个过程的话,那么叫声、电视里传出的音乐不都让这个过程“半中间发生阻隔、停顿或故障而断开”了吗?这不就是活生生的“中断”吗? 在这个场景中,我是唯一具有处理能力的主体,不管是烧水、关水龙头还是看电视,同一个时间点上我只能干一件事情。但是,在我专心致志干一件事情时,总有许多或紧迫或不紧迫的事情突然出现在面前,都需要去关注,有些还需要我停下手头的工作马上去处理。只有在处理完之后,方能回头完成先前的任务,“把一壶水彻底烧开!” 中断机制不仅赋予了我处理意外情况的能力,如果我能充分发挥这个机制的妙用,就可以“同时”完成多个任务了。回到烧水的例子,实际上,无论我在不在厨房,煤气灶总是会把水烧开的,我要做的,只不过是及时关掉煤气灶而已,为了这么一个一秒钟就能完成的动作,却让我死死地守候在厨房里,在10分钟的时间里不停地看壶嘴是不是冒蒸气,怎么说都不划算。我决定安下心来看电视。当然,在有生之年,我都不希望让厨房成为火海,于是我上了闹钟,10分钟以后它会发出“尖叫”,提醒我炉子上的水烧开了,那时我再去关煤气也完全来得及。我用一个中断信号——闹铃——换来了10分钟的欢乐时光,心里不禁由衷地感叹:中断机制真是个好东西。 正是由于中断机制,我才能有条不紊地“同时”完成多个任务,中断机制实质上帮助我提高了并发“处理”能力。它也能给计算机系统带来同样的好处:如果在键盘按下的时候会得到一个......

阅读全文(2068) | 评论:0

位运算(2007-08-31 10:10:00)

摘要:位运算 位运算   在很多系统程序中常要求在位(bit)一级进行运算或处理。C语言提供了位运算的功能, 这使得C语言也能像汇编语言一样用来编写系统程序。一、位运算符C语言提供了六种位运算符:& 按位与| 按位或^ 按位异或~ 取反<< 左移>> 右移1. 按位与运算 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码) 00000001 (1的二进制补码)可见9&5=1。  按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 运算 ( 255 的二进制数为0000000011111111)。main(){int a=9,b=5,c;c=a&b;printf("a=%d\nb=%d\nc=%d\n",a,b,c);}2. 按位或运算 按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。例如:9|5可写算式如下: 00001001|0000010100001101 (十进制为13)可见9|5=13main(){int a=9,b=5,c;c=a|b;printf("a=%d\nb=%d\nc=%d\n",a,b,c);}3. 按位异或运算 按位异或运算符“^”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现,例如9^5可写成算式如下: 00001001^00000101 00001100 (十进制为12)main(){int a=9;a=a^15;printf("a=%d\n",a);}4. 求反运算 求反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。例如~9的运算为: ~(0000000000001001)结果为:11111111111101105. 左移运算 左移运算符“<<”是双目运算符。其功能把“&l......

阅读全文(2372) | 评论:0

C函数(2007-08-13 16:35:00)

摘要: 后一页前一页 D 函数名: delay 功  能: 将程序的执行暂停一段时间(毫秒) 用  法: void delay(unsigned milliseconds); 程序例: /* Emits a 440-Hz tone for 500 milliseconds */ #include <dos.h> int main(void) {    sound(440);    delay(500);    nosound();    return 0; }     函数名: delline 功  能: 在文本窗口中删去一行 用  法: void delline(void); 程序例: #include <conio.h> int main(void) {    clrscr();    cprintf("The function DELLINE deletes \     the line containing the\r\n");    cprintf("cursor and moves all lines \     below it one line up.\r\n");    cprintf("DELLINE operates within the \     currently active text\r\n");    cprintf("window.  Press any key to \     continue . . .");    gotoxy(1,2);  /* Move the cursor to the       second line and first column */    getch(); ......

阅读全文(1921) | 评论:0

C函数(2007-08-13 16:31:00)

摘要: 后一页前一页 C 函数名: cabs 功  能: 计算复数的绝对值 用  法: double cabs(struct complex z); 程序例: #include <stdio.h> #include <math.h> int main(void) {    struct complex z;    double val;    z.x = 2.0;    z.y = 1.0;    val = cabs(z);    printf("The absolute value of %.2lfi %.2lfj is %.2lf", z.x, z.y, val);    return 0; }       函数名: calloc 功  能: 分配主存储器 用  法: void *calloc(size_t nelem, size_t elsize); 程序例: #include <stdio.h> #include <alloc.h> int main(void) {    char *str = NULL;    /* allocate memory for string */    str = calloc(10, sizeof(char));    /* copy "Hello" into string */    strcpy(str, "Hello");    /* display string */    printf("String is %s\n", str);    /* free memory */    free(str);    return 0; }       函数名: cei......

阅读全文(1889) | 评论:0

C函数(2007-08-13 16:19:00)

摘要: 后一页前一页 B 函数名: bar 功  能: 画一个二维条形图 用  法: void far bar(int left, int top, int right, int bottom); 程序例: #include <graphics.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> int main(void) {    /* request auto detection */    int gdriver = DETECT, gmode, errorcode;    int midx, midy, i;    /* initialize graphics and local variables */    initgraph(&gdriver, &gmode, "");    /* read result of initialization */    errorcode = graphresult();    if (errorcode != grOk)  /* an error occurred */    {       printf("Graphics error: %s\n", grapherrormsg(errorcode));       printf("Press any key to halt:");       getch();       exit(1); /* terminate with an error code */    }    midx = getmaxx() / 2;    mid......

阅读全文(1976) | 评论:0

C函数(2007-08-13 16:18:00)

摘要: 后一页前一页回目录回首页 A 函数名: abort 功  能: 异常终止一个进程 用  法: void abort(void); 程序例: #include <stdio.h> #include <stdlib.h> int main(void) {   printf("Calling abort()\n");   abort();   return 0; /* This is never reached */ }     函数名: abs 功  能: 求整数的绝对值 用  法: int abs(int i); 程序例: #include <stdio.h> #include <math.h> int main(void) {   int number = -1234;   printf("number: %d  absolute value: %d\n", number, abs(number));   return 0; }     函数名: absread, abswirte 功  能: 绝对磁盘扇区读、写数据 用  法: int absread(int drive, int nsects, int sectno, void *buffer);  int abswrite(int drive, int nsects, in tsectno, void *buffer); 程序例: /* absread example */ #include <stdio.h> #include <conio.h> #include <process.h> #include <dos.h> int main(void) {   int i, strt, ch_out, sector;   char buf[512];   printf("Insert a diskette into drive A and press ......

阅读全文(1413) | 评论:0

字符屏幕函数(2007-08-13 16:11:00)

摘要:  后一页前一页回目录回首页 字符屏幕函数     Turbo C2.0的字符屏幕函数主要包括文本窗口大小的设定、窗口颜色的设置、 窗口文本的清除和输入输出等函数。     1.文本窗口的定义     Turbo C2.0默认定义的文本窗口为整个屏幕, 共有80列(或40列)25行的文本 单元, 每个单元包括一个字符和一个属性, 字符即ASCII 码字符, 属性规定该字 符的颜色和强度。     Turbo C2.0可以定义屏幕上的一个矩形域作为窗口, 使用window()函数定义。 窗口定义之后, 用有关窗口的输入输出函数就可以只在此窗口内进行操作而不超 出窗口的边界。     window()函数的调用格式为:      void window(int left, int top, int right, int bottom);     该函数的原型在conio.h 中 (关于文本窗口的所有函数其头文件均为conio.h, 后面不再说明)。 函数中形式参数(int left,  int top)是窗口左上角的坐标, (int right, int  bottom)是窗口的右下角坐标, 其中(left,  top)和(right, bottom) 是相对于整个屏幕而言的。 Turbo C 2.0规定整个屏幕的左上角坐标为 (1, 1), 右下角坐标为(80, 25)。并规定沿水平方向为 X轴, 方向朝右; 沿垂直 方向为 Y轴, 方向朝下。若window()函数中的坐标超过了屏幕坐标的界限, 则窗 口的定义就失去了意义, 也就是说定义将不起作用, 但程序编译链接时并不出错。     另外, 一个屏幕可以定义多个窗口, 但现行窗口只能有一个(因为DOS为单任 务操作系统), 当需要用另一窗口时, 可将定义该窗口的window() 函数再调用一 次, 此时该窗口便成为现行窗口了。     如要定义一个窗口左上角在屏幕(2......

阅读全文(1515) | 评论:0

C图形函数(2007-08-13 15:58:00)

摘要:Turbo C提供了非常丰富的图形函数, 所有图形函数的原型均在graphics. h 中, 本节主要介绍图形模式的初始化、独立图形程序的建立、基本图形功能、图 形窗口以及图形模式下的文本输出等函数。另外, 使用图形函数时要确保有显示 器图形驱动程序*BGI, 同时将集成开发环境Options/Linker中的Graphics lib选 为on, 只有这样才能保证正确使用图形函数。     1. 图形模式的初始化     不同的显示器适配器有不同的图形分辨率。即是同一显示器适配器, 在不同 模式下也有不同分辨率。因此, 在屏幕作图之前, 必须根据显示器适配器种类将 显示器设置成为某种图形模式, 在未设置图形模式之前, 微机系统默认屏幕为文 本模式(80列, 25行字符模式), 此时所有图形函数均不能工作。设置屏幕为图形 模式, 可用下列图形初始化函数:      void far initgraph(int far *gdriver, int far *gmode, char *path);     其中gdriver和gmode分别表示图形驱动器和模式, path是指图形驱动程序所 在的目录路径。有关图形驱动器、图形模式的符号常数及对应的分辨率见表2。     图形驱动程序由Turbo C出版商提供, 文件扩展名为.BGI。根据不同的图形 适配器有不同的图形驱动程序。例如对于EGA、 VGA 图形适配器就调用驱动程序 EGAVGA.BGI。                表2. 图形驱动器、模式的符号常数及数值 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━      图形驱动器(gdriver)          图形模式(gmode)    ───────────  &n......

阅读全文(2374) | 评论:0