2009年3月20日星期五

Linux 下编译C程序

GCC 已不再是主要针对GNU项目自身的软件的小型 C
语言编译器了。如今,它已支持了许多不同的语言,包括
C、C++、Ada、Fortran、Objective C,甚至还有Java。事实上,现代 Linux
系统除了可以自豪地炫耀那些由 GNU
工具直接支持的语言以外,它还支持大量其他语言。日益流行的脚本语言
Perl、Python 和 Ruby,以及正在不断发展的mono
可移植C#实现的确有助于冲淡人们对 Linux
编程的传统看法,但这完全是另外一个问题了。

Linux 内核和许多其他自由软件以及开放源码应用程序都是用 C 语言编写并使用
GCC 编译的。

1. 编译单个源文件

为了进行测试,你可以创建"Hello World"程序:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
printf("Hello world!\n");
exit(0);
}

使用如下命令编译并测试这个代码:
# gcc -o hello hello.c
# ./hello
Hello wordl!

在默认情况下产生的可执行程序名为a.out,但你通常可以通过 gcc
的"-o"选项来指定自己的可执行程序名称。

2. 编译多个源文件

源文件message.c包含一个简单的消息打印函数:

#include <stdio.h>

void goodbye_world(void)
{
printf("Goodbye, world!\n");
}

使用gcc的"-c"标记来编译支持库代码:
# gcc -c message.c

这一过程的输出结果是一个名为message.o的文件,它包含适合连接到一个较大程序的已编译目标代码。

创建一个简单的示例程序,它包含一个调用goodbye_world的main函数

#include <stdlib.h>

void goodbye_world(void):

int main(int argc, char **argv)
{
goodbye_world();
exit(0);
}

使用GCC编译这个程序:
# gcc -c main.c

现在有了两个目标文件: message.o 和 main.o 。它们包含能够被 Linux
执行的目标代码。要从这个目标代码创建Linux可执行程序,需要再一次调用 GCC
来执行连接阶段的工作:
# gcc -o goodbye message.o main.o

运行编译结果:
# ./goodbye
Goodbye, world!

前面这些单独的步骤也可以简化为一个命令,这是因为 GCC
对如何将多个源文件编译为一个可执行程序有内置的规则。
# gcc -o goodbye message.c main.c
# ./goodbye
Goodbye, world!

3. 使用外部函数库

GCC 常常与包含标准例程的外部软件库结合使用,几乎每一个 Linux
应用程序都依赖于由 GNU C 函数库 GLIBC。
应用外部函数库的例子:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX_INPUT 25

int main(int agrc, char **argv)
{
char input[MAX_INPUT];
double angle;

printf("Give me an angle (in radians) ==>");
if(!fgets(input, MAX_INPUT, stdin)){
perror("an error occurred.\n");
}
angle = strtod(input, NULL);

printf("sin(%e) = %e\n", angle, sin(angle));

return 0;
}

编译命令:
# gcc -o trig -lm trig.c

GCC 的"-lm"选项,它告诉 GCC
查看系统提供的数学库(libm)。因为Linux和UNIX的系统函数库通常以"lib"为前缀,所以我们假设它存在。真正的函数库位置随系统的不同而
不同,但它一般会位于目录/lib或/usr/lib中,在这些目录中还有数以百计的其他必需的系统函数库。

4. 共享函数库与静态函数库

Linux系统上的函数库分为两种不同的类型:共享的和静态的

静态函数库:每次当应用程序和静态连接的函数库一起编译时,任何引用的库函数中的代码都会被直接包含进最终的二进制程序。

共享函数库:包含每个库函数的单一全局版本,它在所有应用程序之间共享。这一过程背后所涉及的机制相当复杂,但主要依靠的是现代计算机的虚拟内存能力,它允许包含库函数的物理内存安全地在多个独立用户程序之间共享。

使用共享函数库不仅减少了文件的容量和 Linux
应用程序在内存中覆盖的区域,而且它还提高了系统的安全性。一个被许多不同程序同时调用的共享函数库很可能会驻留在内存中,以在需要使用它时被立即使用,
而不是位于磁盘的交换分区中。这有助于进一步减少一些大型 Linux
应用程序的装载时间。

将上面的 message.c 作为共享库函数使用的例子:

# gcc -fPIC -c message.c
"PIC"命令行标记告诉 GCC
产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译输出的文
件 message.o 可以被用于建立共享函数库,我们只需使用gcc的"-shared"标记即可:
# gcc -shared -o libmessage.so message.o

将上面的mian.c使用共享库函数ligmessage.so编译:
# gcc -o goodbye -lmessage -L. message.o
"-lmessage"标记来告诉 GCC 在连接阶段引用共享函数库 libmessage.so
。"-L."标记告诉 GCC 函数库可能位于当前目录中,否则 GNU
的连接器会查找标准系统函数库目录,在本例的情况下,就找不到可用的函数库了。

此时运行编译好的goodbye会提示找不到共享函数库:
#./goodbye
./goodbye: error while loading shared libraries: libmessage.so: cannot
open shared object file: No such file or directory

可以使用命令 ldd
来发现一个特定应用程序需要使用的函数库。ldd搜索标准系统函数库路径并显示一个特定程序使用的函数库版本。

#ldd goodbye
linux-gate.so.1 => (0×00493000)
libmessage.so => not found
libc.so.6 => /lib/libc.so.6 (0×0097c000)
/lib/ld-linux.so.2 (0×0095a000)

库文件 libmessage.so
不能在任何一个标准搜索路径中找到,而且系统提供的配置文件 /etc/ld.so.conf
也没有包含一个额外的条目来指定包含该库文件的目录。

需要设置一个环境变量LD_LIBRARY_PATH来制定额外的共享函数库搜索路径,
# export LD_LIBRARY_PATH=`pwd`
# ldd goodbye
linux-gate.so.1 => (0x002ce000)
libmessage.so => /tmp/cpro/libmessage.so (0x00b0f000)
libc.so.6 => /lib/libc.so.6 (0x0097c000)
/lib/ld-linux.so.2 (0x0095a000)
运行程序
# ./goodbye
Goodbye, world!

gcc在命令行上经常使用的几个选项是:
-c
只预处理、编译和汇编源程序,不进行连接。编译器对每一个源程序产生一个目标文件。
-o file 确定输出文件为file。如果没有用-o选项,缺省的可执行文件的输出是
a.out,目标文件和汇编文件的输出对source.suffix分别是source.o和source.s,预处理的C源程序的输出是标准输出stdout。
-Dmacro或-Dmacro=defn 其作用类似于源程序里的#define。例如:% gcc -c
-DHAVE_GDBM -DHELP_FILE=\"help\" cdict.c其中第一个-
D选项定义宏HAVE_GDBM,在程序里可以用#ifdef去检查它是否被设置。第二个-D选项将宏HELP_FILE定义为字符串"help"(由于
反斜线的作用,引号实际上已成为该宏定义的一部分),这对于控制程序打开哪个文件是很有用的。
-Umacro
某些宏是被编译程序自动定义的。这些宏通常可以指定在其中进行编译的计算机系统类型的符号,用户可以在编译某程序时加上
-v选项以查看gcc缺省定义了哪些宏。如果用户想取消其中某个宏定义,用-Umacro选项,这相当于把#undef
macro放在要编译的源文件的开头。
-Idir
将dir目录加到搜寻头文件的目录列表中去,并优先于在gcc缺省的搜索目录。在有多个-I选项的情况下,按命令行上-I选项的前后顺序搜索。dir可使用相对路径,如-I../inc等。
-O
对程序编译进行优化,编译程序试图减少被编译程序的长度和执行时间,但其编译速度比不做优化慢,而且要求较多的内存。
-O2 允许比-O更好的优化,编译速度较慢,但结果程序的执行速度较快。
-g
产生一张用于调试和排错的扩展符号表。-g选项使程序可以用GNU的调试程序GDB进行调试。优化和调试通常不兼容,同时使用-g和-O(-O2)选项经常会使程序产生奇怪的运行结果。所以不要同时使用-g和-O(-O2)选项。
-fpic或-fPIC 产生位置无关的目标代码,可用于构造共享函数库。
以上是gcc的编译选项。gcc的命令行上还可以使用连接选项。事实上,gcc将所有不能识别的选项传递给连接程序ld。连接程序ld将几个目标文件和库
程序组合成一个可执行文件,它要解决对外部变量、外部过程、库程序等的引用。但我们永远不必要显式地调用ld。利用gcc命令去连接各个文件是很简单的,
即使在命令行里没有列出库程序,gcc也能保证某些库程序以正确的次序出现。
gcc的常用连接选项有下列几个:
-Ldir
将dir目录加到搜寻-l选项指定的函数库文件的目录列表中去,并优先于gcc缺省的搜索目录。在有多个-L选项的情况下,按命令行上-L选项的前后顺序搜索。dir可使用相对路径。如-L../lib等。
-lname
在连接时使用函数库libname.a,连接程序在-Ldir选项指定的目录下和/lib,/usr/lib目录下寻找该库文件。在没有使用-static选项时,如果发现共享函数库libname.so,则使用libname.so进行动态连接。
-static 禁止与共享函数库连接。
-shared 尽量与共享函数库连接。
这是Linux上连接程序的缺省选项。下面是一个使用gcc进行连接的例子:
% gcc -o prog main.o subr.o -L../lib -lany -lm

One man writes Linux drivers for 235 USB webcams

就是他!这位抽着大烟袋锅子的老家伙;)

这些Made in
China的廉价摄像头,都没有驱动程序,这位Linux爱好者一怒之下写了235个USB摄像头的驱动程序。
最近好像免驱动摄像头比较火爆,但是我对这种摄像头在Linux下的驱动还是担忧哦,这些厂商,基本上不会考虑Linux用户的。
所以,我们要感谢这样的人!
看看支持的列表吧!
最后,让我们记住这个名字, Michel Xhaard


A LONE HOBBYIST

programmer sitting at his home in France is responsible for adding 235 USB
webcams to the list of those supported by Linux. He tells the INQUIRER
about this often unknown and unrecognised achievement.Near three years
ago, I purchased the cheapest USB webcams - actually, pair - I could find
at the time, without taking into consideration whether those webcams
worked with Linux or not. I ran one desktop PC with Win2K and one of the
webcams was plugged to that box. I quickly found out several things:
first, "Made in China" webcams surely are cheap, but that comes at a price
of often having no support web site, no physical address of the
manufacturer, and no updates to its drivers. The Win2K drivers for the
"DigiGR8″ 301P had apparently a memory leak under Win2k, forcing me to
reboot the win2k box on a daily basis. Basically it just stopped working
after a dozen hours of continuous use, and rebooting was the only solution.

I then concluded I had enough with Win2K and decided to install my Linux
distro of choice - back then Sun Microsystem's ill-fated Java Desktop
System for Linux R2. It soon became evident that the device was a
power-sucking brick as far as Linux compatibility was concerned. After
finding the chipset used by the webcam and writing to both the chipset
manufacturer and the webcam builder and receiving no reply whatsoever, I
was on my own. I asked on the newsgroups, and was told that the ZC0301
chipset, manufactured by "Z-Star Corp" -a firm now apparently going by the
name Vimicro Corp- was on the "Linux (in)compatibility list".


All 235 low-cost webcams supported in Linux thanks to… this man

Imagine my surprise when, by pure chance, I found out last week that there
are now Linux drivers for hundreds of those cheap "Made in China" webcams
with strange brand names and a Vimicro chipset inside. The surprise was
more shocking when I realized that drivers for 235 webcams - at the time
of this writing - are the work of a single unknown hero who works from his
home in France, does so with no corporate sponsorship, and what's even
more outrageous, very few people know about the existence of those drivers
and about the person behind them.


Project web page showing some of the supported USB Webcam chipsets


More webcams supported


…near the end of the list.

FC: Who are you and what do you do?
MX: My name is Michel Xhaard, I am a Physician and work in Doppler and
Ultrasound imaging for years. I am now near 60 years old.

FC: Interesting, as it kind of breaks the "young school kit" stereotype of
the Linux advocates. When did you start in this project and why?.
MX: I started working on the "spca50x" project in 2003, when I bought two
webcams for my daughters for Christmas but there was no support under
Linux for those.

FC: So you decided to take matters in your own hands. How did you know
where to start?
MX: After asking the gPhoto team, Till Adam (http://hubbahubba.de/) and
Thomas G. (http://home.tiscali.dk/tomasgc/labtec/) provided me with some
useful help to start. Few weeks later we had full support of the Sunplus
spca504b chipset in Gphoto -userspace picture support- and Spca50x for
video streaming.

FC: Why "GSPCA"? What does it stand for?
MX: "Generic Software Package for Camera Adapters" :)

FC: So how did the ice ball grow to reach today's 253+ webcams supported
with several different chipsets?
MX: Starting with the Sunplus chipset support, I realised that most code
in the core driver could be "shareable" to support several webcam
chipset(s). That is why the "GSPCA" drivers now support over 250 webcams
from different chipset vendors.


Linux application GnomeMeeting (Netmeeting clone, now renamed Ekiga)
detecting USB webcam

FC: May I ask you why you decided to host your project web site on
Free.FR? Don't you think Sourceforge.Net or other such OSS project
repository would be more appropriate? What if Free.FR disappears?. In a
sense, don't you think it's as risky as hosting an OSS project on
Geocities or Tripod?
MX: I like "free.fr" because it is, well, free :) Have you seen the same
content in Geocities.com or tripod.com ??. Check out ftp://ftp.free.fr/pub/
Also, you can be sure that "free.fr" will not disappear. I personally
don't like Sourceforge.net because it can be at times too slow, and
there's a lot of dead projects …

FC: Are you aware that your site is not very well indexed?. I came across
not one but three pages claiming that the ZC0301 was not supported, or
that there was a Linux driver project, which got abandoned (true, but
outdated). Don't you think that having a domain name would help?
MX: Yes.

FC: How do you feel knowing that there are a few really big corporations
with million dollar budgets all peddling Linux, and you do all this
critical work of helping Linux gain webcams support -by the hundreds!-,
yet not a single one of those big firms has decided to formally sponsor
your work?
MX: my work is not "Linux Kernel centred" my goal is to provided video
input support for Linux users, and I am not sure that these big companies
are interested in the end user :).

FC: well, I think they should. Google does, for instance, since they
bought this Nordic firm days ago which does cross-platform video
conferencing software in Java. So if they want everyone to do video
conferencing regardless of OS, drivers suddenly is an issue. OK, you won't
say it but I will: shame on RedHat, Novell, Linspire, and IBM, to name
just a few, for not caring about this. Is there anything you want to add?.
MX: Yes, that despite the old picture you are going to use on the article,
notice that I stopped smoking in June 2006. :) [I'm sure Mr. Ballmer will
be sending you tons of tobacco after reading this article]. :)

FC: Thanks very much Michel for your time, and for the drivers as well. I
see that the ZC0301P chipset used in my "DigiGR8″ webcam is listed, but I
haven't been able to make my webcam work yet, so let's cut the chat and
start the (virtual) hair-pulling exercise.
MX: You're welcome. µ

一位法国人在他自己的房间里,为Linux增添了对235种USB摄像头的支持。他向INQUIRER(一个媒体)述说了这种在开源世界经常都存在的,默默无闻的贡献行为。

大约在三年前,我购买了一些最便宜的USB摄像头,当然,那个时候我并没有想过它是否可以在Linux下面正常使用。当时,我PC上的系统是Windows
2000,我准备在上面使用我的USB摄像头。慢慢地,我发现了一些问题:首先,"Made
in
China",这东西真是相当的便宜,但是,既然是便宜货,也就说明没有支持网站,没有生产厂址,没有升级的驱动程序。Win2k中,针对"DigiGR8"的驱动程序301P似乎有内存泄露的问题,因为它使我的系统经常重启。基本上,每十二小时抽风一次,重启是唯一的办法。

之后,我对Win2k说拜拜了,转而去使用Linux,我选择的是比较稳定的Sun的Java桌面系统。Linux下自然无法避免"驱动程序"这个一直以来都很尴尬的问题。我给这个USB摄像头使用的芯片的制造商写了E-mail,也给组装商写过,但都毫无回应。好吧,我觉得这个问题只有我自己来解决了。我开始在新闻组上求助,他们说这是ZC0301芯片,制造商是Z-Star,它似乎与名列Linux支持列表中的Vimicro有关。

我很吃惊,一个偶然的机会,上周我发现在Linux形形色色的针对"Made in
China"廉价USB摄像头的驱动中,有Vimicro芯片的支持。更令我惊讶的是,在我写这篇文章之际,那个驱动已经可以支持235种USB摄像头
--
这是一名在法国的无名英雄贡献的。没有商业支持,也很少人有知道这些驱动与它们背后的作者。

(以下是采访内容)

-- ./images/2008-11-16_Michel_X.png --

(All 235 low-cost webcams supported in Linux thanks to... this man)

FC:介绍一下你自己吧。
MX:我的名字叫Michel
Xhaard,是一名内科医生,主要研究领域是超声波成像方面。今年60年。

FC:看来Linux的拥护者中不光是年青人些啊。你是什么时候开始这个项目,又是出于什么目的呢?
MX:是在2003年的时候,我开始参与"spca50x"这个项目。那时,我给我的两个女儿买了两个USB摄像头作为圣诞礼物,但是,它们却不能在Linux下使用。

FC:所有,你就决定自己干了?你是怎么知道从哪里开始着手的呢?
MX:是这样的。我在[url=http:www.gphoto.org/]gPhoto[/url]这个项目组得到了很多帮助,特别感谢[url=http:hubbahubba.de/]Till
Adam[/url]
和Thomas G.。几周后,我在gPhoto得到了"Sunplus
spca504b"芯片组的驱动,还有"Spca50x"的。

FC:什么是"GSPCA"?
MX:"Generic Software Package for Camera Adapters" : )

FC:那之后,你是怎么做到对各种各样的芯片组的驱动支持,以至达到了253种之多的呢?
MX:从"Sunplus"这个芯片的驱动开始,我发现驱动程序中的核心部分代码,大部分都可以用来支持其它的USB摄像头芯片,所以,现在的"GSPCA"可以支持250种USB摄像头了。

FC:我能问下,为什么你决定把你的项目主页放到Free.FR?为什么不是Sourceforge.Net或其它的一些开源软件支持机构,我是说,那些机构或许更容易得到资助。Free.FR是什么样的呢?比如说,就像你把一个开源项目放到Geocities或Tripod要承担的风险之类的。
MX:我喜欢"free.fr",它很好,自由 : )
这些你在Geocities.com或tripod.com能看到吗?看看ftp://ftp.free.fr/pub/吧。我坚信"free.fr"会一起做下去的。从我个人而言,我不太喜欢Sourceforge.net,因为它进展得太慢了,而且上面有很多死项目。

FC:你有注意,你的站点在索引,宣传方面做得不是很好吗?我曾经在三个页面见过,说ZC0301在Linux下没有驱动,也许曾经有过想支持ZC0301的项目,但找不到了。你认为如果有一个好点域名,那会给你带来一些帮助吗?
MX:是的。

FC:当你了解到,只有很少的大公司会出钱去支持Linux平台,而你所做的工作却让Linux支持了上百种USB摄像头设备时作何感想?有没有公司愿意资助你的工作呢?
MX:我做的工作并不是一个Linux的关键核心,我只是想为Linux的用户们,在视频输入方面做点事。我不太清楚那些大公司些是否在意这群用户
: )

FC:嗯,我觉得它们应该要在意了。Google是这样的,它前几天才收购了用Java实现跨平台视频会议解决方案的Nordic。所以,如果他们想让所有人在任何操作系统上都能进行视频会议,那驱动程序的问题就不得不考虑了。好吧,也许你不想,但是我要说了,我为RedHat,
Novell, Linspire,
IBM等这些不关心驱动程序问题的公司感觉羞耻。你还有什么需要补充的吗?
MX:是的,那个,你用在这篇文章中的我的照片,事实上,我在2006年6月就戒烟了:
) [我肯定Mr. Ballmer看过这篇文章后会送你很多烟的]: )

FC:非常感谢Michel接受采访,也非常感谢你贡献的那些驱动程序。还有那个,我看见在你的驱动程序的支持列表中有我的"DigiGR8"的ZC0301P芯片,但是我还是没搞定。好了,谈话结束,让我们开始干正事吧。
MX:乐意奉陪。

Unix常用监控和管理命令

ps:查看系统中的进程,Linux中可以使用ps -aux查看所有进程
参数w表示加宽显示的命令行,参数w可以写多次,通常最多写3次,表示加宽3次,这足以显示很长的命令行了。
例如:ps -auxwww

top:显示系统内存、cpu使用情况,并可自动刷新进程列表

vmstat:显示当前的内存使用情况

netstat:显示网络状况,使用参数p可以查看对应的进程号及程序名,
通常使用参数a(显示所有连接情况)和n(不反查域名和服务名),
例如:netstat -anp

查看服务器侦听情况,使用:
netstat -an | grep LISTEN

查看服务器已建立的连接,使用:
netstat -an | grep ESTABLISHED

ifconfig:查看(或设置)网络设备信息
ifconfig -a:查看所有网络设置信息

last:显示登录到服务器的情况以及服务器重启情况

df:显示硬盘空间及使用情况,Linux下可以带参数h,显示结果更人性化。例如:
df -h 硬盘空间按人性化显示
df -k 硬盘空间按KB显示
df -m 硬盘空间按MB显示

w:显示登录到服务器上的用户列表

以下几个命令仅针对Linux

lsof:显示当前打开的文件列表,包括建立的socket连接等。本命令可以用于程序员检查编写的程序打开的文件数。

sysctl:显示(或设置)系统内核参数
sysctl -a 显示所有内核参数
sysctl -w 参数名=参数值
例如:sysctl -w fs.file-max=10240 设置系统允许同时打开的最大文件数为10240。

内核参数fs.file-nr包括三个参数值,第一个参数表示系统中曾经同时打开过的文件数峰值,
第二个参数表示空闲(分配后已释放)的文件数,
第三个参数表示可以打开的最大文件数,其值等于fs.file-max。

当前打开的文件数 = 第一个参数值 - 第二个参数值

例如:
fs.file-nr = 977 223 10240
当前打开的文件数 = 977 - 233 = 744

设置内核参数时务必小心,如果设置不当会导致系统异常,甚至当机。

ulimit:显示(或设置)用户可以使用的资源限制

ulimit -a 显示用户可以使用的资源限制

ulimit unlimited
不限制用户可以使用的资源,但本设置对可打开的最大文件数(max open files)
和可同时运行的最大进程数(max user processes)无效

ulimit -n <可以同时打开的文件数> 设置用户可以同时打开的最大文件数(max
open files)
例如:ulimit -n 8192
如果本参数设置过小,对于并发访问量大的网站,可能会出现too many open
files的错误

ulimit -u <可以运行的最大并发进程数>
设置用户可以同时运行的最大进程数(max user processes)
例如:ulimit -u 1024

Ubuntu 系统下自启动选项的设置方法

这里说明,Ubuntu 中系统没有了RH系统中的 chkconfig 命令 !

可用一些小工具来管理 Ubuntu 的启动选项:
小工具 rcconf:
#sudo apt-get rcconf
#sudo apt-get install rcconf
root 下运行: #sudo rcconf
功能更全的工具:sysv-rc-conf
#sudo apt-get update
#sudo apt-get install sysv-rc-conf
运行:#sudo sysv-rc-conf
也可以直接加入启动程序,例如把 /etc/init.d/red5 加入到系统自动启动列表中:
#sudo sysv-rc-conf red5 on
其他使用方法见: google::Ubuntu::sysv-rc-conf 命令用法

也可以直接修改
直接改 /etc/rc0.d ~ /etc/rc6.d 和 /etc/rcS.d
下的东西,S开头的表示启动,K开头的表示不启动,
例如:想关闭 Red5 的开机自动启动,只需 #sudo mv /etc/rc2.d/S20red5
/etc/rc2.d/K20red5 就可以了。

Ubuntu自动启动程序

首先,linux随机启动的服务程序都在/etc/init.d这个文件夹里,里面的文件全部都是脚本文件(脚本程序简单的说就是把要运行的程序写
到一个
文件里让系统能够按顺序执行,类似windows下的autorun.dat文件),另外在/etc这个文件夹里还有诸如名为rc1.d,
rc2.d一直到rc6.d的文件夹,这些都是linux不同的runlevel,我们一般进入的X
windows多用户的运行级别是第5级,也就是rc5.d,在这个文件夹下的脚本文件就是运行第5级时要随机启动的服务程序。需要注意的是,在每个rc
(1-6).d文件夹下的文件其实都是/etc/init.d文件夹下的文件的一个软连接(类似windows中的快捷方式),也就是说,在
/etc/init.d文件夹下是全部的服务程序,而每个rc(1-6).d只链接它自己启动需要的相应的服务程序!

要启动scim
(某一程序),我们首先要知道scim程序在哪里,用locate命令可以找到,scim在/usr/bin/scim这里,其中usr表
示是
属于用户的,bin在linux里表示可以执行的程序。这样,我就可以编写一个脚本程序,把它放到/etc/init.d里,然后在rc5.d里做一个相
应的软链接就可以了。

这个脚本其实很简单,就两行:

#!/bin/bash

/usr/bin/scim

第一行是声明用什么终端运行这个脚本,第二行就是要运行的命令。


需要注意的一点是,在rc5.d里,每个链接的名字都是以S或者K开头的,S开头的表示是系统启动是要随机启动的,K开头的是不随机启动的。这
样,你就可以知道,如果我要哪个服务随机启动,就把它名字第一个字母K改成S就可以了,当然,把S改成K后,这个服务就不能随机启动了。因此,我这个链接
还要起名为SXXX,这样系统才能让它随机启动。
在RH下,rc.local是默认启动的最后一个脚本文件,所以,
如果你想要随机启动,还有一种方法就是在rc.local的尾部加入/usr/bin/scim,这样就可以了。

Linux 自动启动程序

1.开机启动时自动运行程序

Linux加载后, 它将初始化硬件和设备驱动,
然后运行第一个进程init。init根据配置文件继续引导过程,启动其它进程。通常情况下,修改放置在
/etc/rc或 /etc/rc.d 或 /etc/rc?.d
目录下的脚本文件,可以使init自动启动其它程序。例如:编辑
/etc/rc.d/rc.local
文件(该文件通常是系统最后启动的脚本),在文件最末加上一行"xinit"或"startx",可以在开机启动后直接进入X-Window。

2.登录时自动运行程序

用户登录时,bash首先自动执行系统管理员建立的全局登录script
:/ect/profile。然后bash在用户起始目录下按顺序查找三个特殊文件中的一个:/.bash_profile、/.bash_login、
/.profile,但只执行最先找到的一个。
因此,只需根据实际需要在上述文件中加入命令就可以实现用户登录时自动运行某些程序(类似于DOS下的Autoexec.bat)。

3.退出登录时自动运行程序

退出登录时,bash自动执行个人的退出登录脚本/.bash_logout。例如,在/.bash_logout中加入命令"tar
-cvzf c.source.tgz *.c",则在每次退出登录时自动执行 "tar" 命令备份 *.c
文件。

4.定期自动运行程序

Linux有一个称为crond的守护程序,主要功能是周期性地检查
/var/spool/cron目录下的一组命令文件的内容,并在设定的时间执行这些文件中的命令。用户可以通过crontab
命令来建立、修改、删除这些命令文件。

例如,建立文件crondFile,内容为"00 9 23 Jan *
HappyBirthday",运行"crontab
cronFile"命令后,每当元月23日上午9:00系统自动执行"HappyBirthday"的程序("*"表示不管当天是星期几)。

5.定时自动运行程序一次

定时执行命令at 与crond
类似(但它只执行一次):命令在给定的时间执行,但不自动重复。at命令的一般格式为:at
[ -f file ] time
,在指定的时间执行file文件中所给出的所有命令。也可直接从键盘输入命令:

$ at 12:00
at>mailto Roger -s ″Have a lunch″ < plan.txt
at>Ctr-D
Job 1 at 2000-11-09 12:00
2000-11-09 12:00时候自动发一标题为"Have a
lunch",内容为plan.txt文件内容的邮件给Roger。?9 12:00
2000-11-09 12:00时候自动发一标题为"Have a
lunch",内容为plan.txt文件内容的邮件给Roger。er。ger。er。

Ubuntu 开机自动挂载windows分区

要挂载NTFS格式分区,需要NTFS-3g这个软件。它短小精悍,而且功能强大。
NTFS-3g是一个开源软件,它支持在Windows下面读写NTFS格式的分区。它非常的快速,同时也很安全。它支持Windows
2000、XP和2003,并且支持所有的符合POSIX标准的磁盘操作。

首先要编辑sources.list
#sudo gedit /etc/apt/sources.list

Ubuntu Drapper添加:
deb http://givre.cabspace.com/ubuntu/ dapper main main-all
deb http://ntfs-3g.sitesweetsite.info/ubuntu/ dapper main main-all
deb http://flomertens.keo.in/ubuntu/ dapper main main-all

Ubuntu Edgy添加:
deb http://givre.cabspace.com/ubuntu/ edgy main
deb http://ntfs-3g.sitesweetsite.info/ubuntu/ edgy main
deb http://flomertens.keo.in/ubuntu/ edgy main

同时必须导入GPG-Key,可以这样:
#wget http://flomertens.keo.in/ubuntu/givre_key.asc -O- | sudo apt-key add
-
#wget http://givre.cabspace.com/ubuntu/givre_key.asc -O- | sudo apt-key
add -

现在更新一下源:
#sudo aptitude update

正式安装

在"终端"下面运行:
#sudo apt-get install ntfs-3g

配置NTFS-3g

首先看一些硬盘分区的分区类型
#sudo fdisk -l

现在就可以修改
/etc/fstab,来让Ubuntu启动的时候自动挂载NTFS分区了。但是首先请备份一下这个文件:
#sudo cp /etc/fstab /etc/fstab.bak

建立挂载点,譬如挂载在 /media/windows 下面
#sudo mkdir /media/windows

现在可以在 /etc/fstab 的后面添加
/dev/hda1 /media/ ntfs-3g defaults,locale=zh_CN.utf8 0 0
根据自己的情况进行修改。

一些示例

挂载 /dev/hda3
添加 /dev/hda3 /media/windows ntfs-3g ro,locale=zh_CN.utf8,uid=1000 0 0

关于自己的locale

可以用下面的命令查看所有的locale
#locale -a

如果不想重新启动,就可以
#sudo umount -a
#sudo mount -a

最后一个挂载FAT分区的命令
#sudo mount /dev/hda3 /media/windows/ -t vfat -o iocharset=utf8,umask=000

当然可以在/etc/fstab里面添加
/dev/hda3 /media/windows vfat iocharset=utf8,umask=000 0 0

Openfire随着Ubuntu自动启动

openfire缺省情况下,是不随机启动的。为了解决每次都要手工启动的麻烦,我编写了一个脚本,放在/etc/init.d目录里面
#sudo vim /etc/init.d/openfire
内容如下:

#!/bin/sh

openfire_start(){
/etc/openfire/bin/openfire start
}

openfire_stop(){
/etc/openfire/bin/openfire stop
}

case $1 in
start)
openfire_start
;;
stop)
openfrie_stop
;;
*)
echo 'Usage:openfire start|stop'
;;
esac

晶振及其负载电容

什么是负载电容,它对电路上的晶振电容取值有什么影响吗?晶振上接个电阻有什么用?

晶振的负载电容是分别接在晶振的两个脚上和对地的电容,一般在几十皮发。它会影响到晶振的谐振频率和输出幅度,一般订购晶振时候供货方会问你负载电容是多少。晶振上接的一个电阻是反馈作用,使振荡器容易起振。

晶振负载电容取值直接关系到调频的准确度。如果负载电容不够准确,那么买来的晶体准确度就会差,关于负载电容的计算方法即从晶体两端看进去电容的总和。计算公式:
晶振的负载电容=[(Cd*Cg)/(Cd+Cg)]+Cic+△C式中Cd,Cg为分别接在晶振的两个脚上和对地的电容,Cic(集成电路内部电容)+△C(PCB上电容)经验值为3至5pf.

你也许不知道的#define用法: 通过#define连接字符串

最近看com相关的资料,看到CCmdTarget实现com接口的时候,去读了一些宏的定义,在afxdisp.h头文件中

#define BEGIN_INTERFACE_PART(localClass, baseClass) \
class X##localClass : public baseClass \

本来这个宏定义很容易理解的,但是这里多出个X##,我真没见过这种用法,不晓得它是什么用意。
后来问了几个朋友也都不知道。

你知道么?

也许你也不知道~呵呵,最后我还是找到了相关的资料,解读了这个define,还顺便认识了另外两个不常用的define

#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x

x##y表示什么?表示x连接y,举例说:
int n = Conn(123,456); 结果就是n=123456;
char* str = Conn("asdf", "adf")结果就是 str = "asdfadf";
怎么样,很神奇吧

再来看#@x,其实就是给x加上单引号,结果返回是一个const char。举例说:
char a = ToChar(1);结果就是a='1';
做个越界试验char a = ToChar(123);结果是a='3';
但是如果你的参数超过四个字符,编译器就给给你报错了!error C2015: too many
characters in constant :P

最后看看#x,估计你也明白了,他是给x加双引号
char* str = ToString(123132);就成了str="123132";

最后留几个小试验给大家去测测:
#define Dec(x,y) (x-y)
int n = Dec( A(123,1), 1230);
n = Conn(123, Conn(123,332) );
char* str = A("12", ToString( Dec(3,1));
结果会如何呢? 嘿嘿嘿嘿~


其他一些杂七杂八的东西:
我先定义了一个宏
#define TE text
我想再定义一个宏,能将TE变为字符串("text").
即定义:
#define STR(str) ??? //使用STR(TE)时能替换为"text"。
请问???部分怎么实现呢?用#str是达不到目的的了,用'"'##str##'"'也不对。

#不能做二次替换,可以再定义一个中间宏
#define TE text
#define AD TE
#define STR(AD) #AD
试试

直接定义两个宏得了!
#define TE text
#define TE_S "text"


#define STR abc
char arr[10] = "STR";
为什么arr数组中是STR而不是abc,define不是简单的字符替换吗?

#define A "aaa"
#define B "bbb"A
我对macro这个东西不大熟悉……不过这样可以成功printf("%s\n",B);


在#define中,标准只定义了#和##两种操作。#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串。
#include <stdio.h>
#define paster( n ) printf( "token " #n" = %d\n ", token##n )
int main()
{
int token9=10;
paster(9);
return 0;
}
输出为
[leshy@leshy src]$ ./a.out
token 9 = 10

补充一点: 在用#define 定义时 ,可以用斜杠("\") 续行.与vb中的下划线("
_")作用同.
比如:
#define add1( x, y ) ( x + y)
也可以表示成 :
#define add1(x,y) \
(x + y )

3个普通用法
1.
C: #define X 100 ----> C++: const int x=100;

2.
C: #define MAX(a,b) ((a)>(b)?(a):(b))
C++: inline int max(int a,int b){ return a>b?a:b;}

3.
#ifndef NULL
#define NULL ((void*)0)