⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 回复the linux gcc howto中译版 (转--缩水版)。.txt

📁 LINUX下的安装声卡等操作和技巧介绍
💻 TXT
字号:
作者:L772
email: L772@263.net
日期:8/28/2001 1:51:24 PM
gcc是一个与ANSI相容的编译器;奇怪的是,目前大多数的程式码都不符合ANSI所 
定的标准。如果你热爱ANSI,喜欢用ANSI提供的标准来撰写C程式,似乎除了加 
上-traditional的旗号之外,就没有其它什麽可以多谈的了。There is a 
certain amount of finer-grained control over which varieties of brain 
damage to emulate;请自行查阅gcc info page。 

要注意的是,尽管你用了-traditional来改变语言的特性,它的效果也仅局限 
於gcc所能够接受的□围。例如, -traditional会打开-fwritable-strings,使得 
字串常数移至资料记忆体空间内(从程式码记忆体空间移出来,这个地方是不能任 
意写入的)。这样做会让程式码的记忆体空间无形中增加的。 

前置处理器的符号卯上函数原型宣告 

最常见的问题是,如众所皆知,Linux中有许多常用的函数都定义成巨集存放在标 
头档内,此时若有相似的函数原型宣告出现在程式码内,前置处理器会拒绝进行 
语法分析的前置作业。常见的有atoi()与atol()。 

sprintf() 

在大部份的Unix系统上,sprintf(string, fmt, ...)传回的是string的指标,然 
而,这方面Linux(遵循ANSI)传回的却是放入string内的字元数目.进行移植时 
,尤其是针对SunOS,需有警觉的心。 

fcntl 与相关的函数;FD_*家族的定义到底摆在哪里? 

就在里头。 为了真正的原型宣告,当你用了fcntl,可能你也想含 
括标头档进来。 

一般而言,函数的manual page会在SYNOPSIS章节内列出需要的标头档。 

select()的计时---程式执行时会处於忙碌-等待的状态 

很久很久以前,,select()的计时参数只有唯读的性而已。即使到了最近 
,manual pages仍然有下面这段的警告: 

select()应该是藉由修正时间的数值(如果有的话),再传回自原始计时开始 
後所剩馀的时间。未来的版本可能会使这项功能实现。因此,就目前而言,若 
以为呼叫select()之後,计时指标仍然不会被修正过,可是一种非常不明智的 
想法喔! 

未来就在我们的眼前了!至少,在这儿你绝对可以看到。函数select()传回的, 
是扣除等待尚未到达的资料所耗费的时间後,其剩馀的时间数值。如果在计时结 
束时,都没有资料传送进来,计时引数便会设为0;如果接著还有任何 
的select(),以同样的计时structure来呼叫,那麽select()便会立刻结束。 

若要修正这项问题,只要每次呼叫select()前,都把计时数值放到计时 
structure内,就没有问题了。把下面的程式码, 

struct timeval timeout; 
timeout.tv_sec = 1; timeout.tv_usec = 0; 
while (some_condition) 
select(n,readfds,writefds,exceptfds,&timeout); 

改成, 

struct timeval timeout; 
while (some_condition) { 
timeout.tv_sec = 1; timeout.tv_usec = 0; 
select(n,readfds,writefds,exceptfds,&timeout); 
} 

这个问题,在有些版本的Mosaic里是相当著名的,只要一次的等待,Mosaic就挂 
在那里了。Mosaic的萤幕右上角,是不是有个圆圆的、会旋转的地球动画。那颗 
球转得愈快,就表示资料从网路上传送过来的速率愈慢! 

产生中断的系统呼叫 

特徵: 

当一支程式以Ctrl-Z中止、然後再重新执行时□或者是其它可以产生Ctrl-C中断 
信号的情况,如子程序的终结等□系统就会抱怨说"interrupted system call"或 
是"write: unknown error",或者诸如此类的讯息。 

问题点: 

POSIX的系统检查信号的次数,比起一些旧版的Unix是要多那麽一点。如果 
是Linux,可能就会执行signal handlers了□ 

* 非同步地(计时器的滴答声) 
* 系统呼叫的传回值 
* 在下列系统呼叫的执行期间∶ select(), pause(), connect(),accept(), 
read() on terminals, sockets, pipes or files in /proc, write() on 
terminals, sockets, pipes or the line printer, open() on FIFOs, 
PTYs or serial lines,ioctl() on terminals, fcntl() with command 
F_SETLKW, wait4(), syslog(), any TCP or NFS operations. 

就其它的作业系统而言,你需要的可能就是下面这些系统呼叫了: creat(), 
close(), getmsg(), putmsg(), msgrcv(), msgsnd(), recv(), send(), 
wait(), waitpid(), wait3(), tcdrain(), sigpause(), semop() to this 
list. 

在系统呼叫期间,若有一信号(那支程式本身应准备好handler因应了)产生 
,handler就会被呼叫。当handler将控制权转移回系统呼叫时,它会侦测出它已 
经产生中断,而且传回值会立刻设定成-1,而errno设定成EINTR。程式并没有想 
到会发生这种事,所以就挂了。 

有两种修正的方法可以选择: 

(1) 对每个你自行安装的signal handler,都须在sigaction的旗号加 
上SA_RESTART。例如,把下列的程式, 

signal (sig_nr, my_signal_handler); 

改成, 

signal (sig_nr, my_signal_handler); 
{ struct sigaction sa; 
sigaction (sig_nr, (struct sigaction *)0, &sa); 
#ifdef SA_RESTART 
sa.sa_flags |= SA_RESTART; 
#endif 
#ifdef SA_INTERRUPT 
sa.sa_flags &= ~ SA_INTERRUPT; 
#endif 
sigaction (sig_nr, &sa, (struct sigaction *)0); 
} 

要注意的是,当这部份的变更大量应用到系统呼叫之後,呼叫read()、write() 
、ioctl()、 select()、 pause() 与 connect()时,你仍然得自行检查EINTR。 
如下所示: 

(2) 你自己得很明确地检查EINTR: 

这里有两个针对read()与ioctl()的例子。 

原始的程式片段,使用read(): 

int result; 
while (len > 0) { 
result = read(fd,buffer,len); 
if (result < 0) break; 
buffer += result; len -= result; 
} 

修改成, 

int result; 
while (len > 0) { 
result = read(fd,buffer,len); 
if (result < 0) { if (errno != EINTR) break; } 
else { buffer += result; len -= result; } 
} 

原始的程式片段,使用ioctl(): 

int result; 
result = ioctl(fd,cmd,addr); 

修改成, 

int result; 
do { result = ioctl(fd,cmd,addr); } 
while ((result == -1) && (errno == EINTR)); 

注意一点,有些版本的BSD Unix,其内定的行为是重新执行系统呼叫。若要让系 
统呼叫中断,得使用 SV_INTERRUPT或SA_INTERRUPT旗号。 

可以写入的字串 

gcc对其users总怀抱著乐观的想法,相信当他们打算让某个字串当作常数来用 
时---那它就真的只是字串常数而已。因此,这种字串常数会储存在程式码的记忆 
体区段内。这块区域可以page到磁碟机的image上,避免耗掉swap的记忆体空间, 
而且任何尝试写入的举动都会造成分页的错误(segmentation fault)。这可是一 
种特色呢! 

对老旧一点的程式而言,这可能会产生一个问题。例如,呼叫mktemp(),传递的 
引数(arguments)是字串常数。 mktemp()会尝试著在*适当的位置*重新写入它的 
引数。 

修正的方法 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -