存档

‘Linux’ 分类的存档

linux内核中的软中断的实现

六月 5th, {2010 没有评论 3,576 人阅读过  

最近在阅读linux内核源码,把自己的一些理解发上来,一方面看到的朋友可以帮我指正我理解偏差的地方,别一方面也算是做一个简单的总结。

首先调用open_softirq()函数来初始化软件中断处理函数,将软件中断处理函数根据软中断的下标号插入到softirq_vec数组中,实现过程很简单如下:

1
2
3
4
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
	softirq_vec[nr].action = action;
}

softirq_vec数据有32个元素,对应的是可以有32个软件中断,但实际上linux只是使用了其中的6个软中断,相应的每一个CPU都会有一个对应的32位的掩码__softirq_pending描述挂起的软中断,每一位对应一个软件中断,__soctirq_penging在irq_cpustat_t中定义,如下:

@include/asm/hardirq.h

1
2
3
4
5
6
typedef struct {
	unsigned int	__softirq_pending;
	unsigned long	idle_timestamp;
	unsigned int	__nmi_count;	/* arch dependent */
	unsigned int	__irq_count;	/* arch dependent */
} ____cacheline_aligned irq_cpustat_t;

其中local_softirq_pending()宏用于选择当前CPU所对应的__softirq_penging掩码。相关的宏如下:
@include/linux/irq_cpustat.h

1
2
3
4
#define local_softirq_pending() \
__IRQ_STAT(smp_processor_id() , __softirq_pending)
 
#define __IRQ_STAT(cpu , member) (irq_stat[cpu].member)

接着调用raise_softirq()函数来激活软中断,函数如下:

@kernel/softirq.c

1
2
3
4
5
6
7
8
9
void raise_softirq(unsigned int nr)
{
	unsigned long flags;
	/* 将eflags寄存器的IF标志保存到flags,并且禁用了本地CPU上的中断 */
	local_irq_save(flags);
	raise_softirq_irqoff(nr);
	/* 根据flags变量的值恢复eflags寄存器的IF标志,重新打开本地CPU上的中断 */
	local_irq_restore(flags);
}

raise_softirq_irqoff()函数必须是在禁止中断的情况下执行的,它首先调用__raise_softirq_irqoff()宏激活软件中断,其实也就是设置当前CPU所对应的__softirq_pending所对应的软中断的位,以表示该软中断已激活。如果当前正处于中断或者软中断当中,那么raise_softirq_irqoff执行结束,否则的话就调用wakeup_softirqd()函数激活ksoftirqd/n内核线程来处理软中断。

@kernel/softirq.c

1
2
3
4
5
6
7
inline void raise_softirq_irqoff(unsigned int nr)
{
	__raise_softirq_irqoff(nr);
 
	if (!in_interrupt())
		wakeup_softirqd();
}

__rarse_softirq_irqoff()宏在/include/linux/interput.h中定义:

1
2
3
4
#defome __raise_softirq_irqoff(nr) \
	do{ or_softirq_pending(1UL << (nr)); } while(0)
 
#define or_softirq_pending(x) (local_softirq_pending() |= (x))

其中local_softirq_pending()宏已经在上面列出来了,我不太明白的是__raise_softirq_irqoff()这个宏为什么要放到一个循环里面,它也只是执行了一次,不过linux既然这样写就一定有它的道理,慢慢再去研究吧。

这样软中断已经激活,其处理函数已经加入到了softirq_sec数组中,并且相应的标志位已经合适地设置,系统会周期性地检查已经挂起的软中断,当在local_softirq_pending()中的某个位检测到挂起的软中断的时候,就会调用do_softirq()函数对软中断进行处理。

do_softirq()函数定义如下:
@ kernel/softirq.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
asmlinkage void do_softirq(void)
{
	__u32 pending;
	unsigned long flags;
 
	if (in_interrupt())
		return;
 
	local_irq_save(flags);
 
	pending = local_softirq_pending();
 
	if (pending)
		__do_softirq();
 
	local_irq_restore(flags);
}

如果在中断上下文中调用了do_softirq函数或者禁用了软件中断,那么in_interrupt函数返回1,这时候do_softirq()不做任何事情,否则,它会把eflags寄存器IF标志保存在flags中并禁用中断,然后将local_softirq_pending()的值保存在pending变量中,检测pending的值,如果pending不为0,则表示pending的某一位被设置,当前CPU就有对应的挂起的软中断需要进行处理,调用__do_softirq()对挂起的软中断进行处理,处理完成之后再根据flags变量的值恢复eflags寄存器并打开中断。

接下来看__do_softirq()函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
asmlinkage void __do_softirq(void)
{
	struct softirq_action *h;
	__u32 pending;
	int max_restart = MAX_SOFTIRQ_RESTART;
	int cpu;
 
	pending = local_softirq_pending();
 
	/* 增加preempt_count字段中软中断计数器的值,
	 * 以此来禁用软中断,因为软件中断的可延迟函数
	 * 一般是在开中断的情况下执行的,这样就可能在__do_softirq 执行
	 * 的过程中有别一个__do_softirq的实例正在执行
	 * ,这样就会影响可延迟函数的串行化执行*/
	__local_bh_disable((unsigned long)__builtin_return_address(0));
 
restart:
	set_softirq_pending(0);
 
	local_irq_enable();
 
	h = softirq_vec;
 
	do {
		if (pending & 1) {
			int prev_count = preempt_count();
			/* 执行软件中断处理函数 */
			h->action(h);
			if (unlikely(prev_count != preempt_count())) {
				printk(KERN_ERR "huh, entered softirq %td %p"
				       "with preempt_count %08x,"
				       " exited with %08x?\n", h - softirq_vec,
				       h->action, prev_count, preempt_count());
				preempt_count() = prev_count;
			}
		}
		h++;
		pending >>= 1;
	} while (pending);
	/* 禁用本地软中断 */
	local_irq_disable();
 
	pending = local_softirq_pending();
	if (pending && --max_restart)
		goto restart;
 
	if (pending)
		wakeup_softirqd();
 
	_local_bh_enable();
}

内核循环地检测每一个pending的位,以处理当前位挂机的软件中断,为了防止内核在执行__do_softirq()的过程中不停地有新的softirq产生,以导致内核无暇顾及其它,__do_softirq()在循环检测的时候设置了外层循环的最大次数为10次,对pending的每一位检测10次之后如果pending的值仍不为0,则表示当前CPU仍有未处理的挂起的软件中断,这时候__do_softirq不再对它进行处理,而是唤醒内核线程ksoftirqd/n对它进行处理。
在函数开始的时候,先将软件中断的位图__softirq_pending保存在pending局部变量中,然后调用set_softirq_pending(0)以清空软中断位图,从而允许新的软中断的到来。接着调用local_irq_enable()来激活软中断。

分类: Linux 标签:

SVN使用小结(在google code上管理代码)

四月 6th, {2010 3 条评论 5,030 人阅读过  

前几天发布了openfetion的新协议版本,在Ubuntu中文论坛上发了个贴子宣传了一下,Ubuntu在中国果然不愧是拥有最状大的用户群,以前在其它的开源社区发的时候点击率都很低(当然也可能是大家觉得这个很没意思),不过这次Ubuntu论坛里面的网友们让我很感动,大家回馈了丰富的修改意思,也提交了各种现存的bug,还有的网友帮我打了deb包和rpm包,甚是感动,在这里先谢一下,由于bug太多,一个多星期的时候更新了两个版本,本来这个东西就是做出来玩玩的,看来还是有很多人喜欢的,所以我也决定用继续用我的休息时间把它做下去,之后考虑加上文件传输和非移动号码登陆这些有用的功能。

OK,扯远了,这篇文章是要总结一下svn的用法的,很多人发邮件问我关于飞信相关协议的问题,我也都给一一回复了,可也着实花费了不少的时间,后来就写了几篇相关的文章,仍然有人对一些细节不解,没办法,后来我也管不了那么多了,就把飞信给完全开源了,希望我的行为能对祖国的开源事业做一点小小的贡献吧。

突然觉得sourceforge和google code的svn代码管理很有用,以前在服务器上搭过cvs,后来嫌麻烦就一直没用,看了看svn的一些介绍,发现用起来着实简单方便了不少,于是就想用一用了,本来想在实验室服务器上搭一个的,后来想既然开源了就放到网上跟大家共享吧,gg去香港后在实验室上就很不稳定了,偶尔上得去偶尔上不去,于是想放到sf上去,结果sf的svn服务器教育网不加代理访问不了,抓包看了下svn的协议是TCP承载的TLS,只有http的代理,也不知道行不行,懒得研究就用gg了。

又扯了一大堆费话,总结一下svn的基本命令吧。

svn checkout :简写是svn co
example:

$svn checkout https://ofetion.googlecode.com/svn/trunk/ ofetion –username levin108

这个没什么好说的,跟cvs的checkout一个意思,从版本库中取出一个项目的拷贝,输入后会提示输入验证码,验证通过后会提示是否以保存在本地,保存的话以后就不用输入了。

svn commit :简写是svn ci
example:

$svn commit -m “modified some bugs”

将本地项目拷由的修改提交到版本库藏, 不加-m会的话提示一些乱七八糟的东西,没细看。

svn copy :简写svn cp

复制本地项目副本到版本库

svn move (mv), svn delete (rm,del),svn mkdir

故名思义吧,跟copy差不多,懒得说细地写了。这些操作所做的修改都会保存到本地缓存中,执行svn ci后才会同步到版本库。

svn import
example:

$svn import -m “initial import” https://ofetion.googlecode.com/svn/trunk/ ofetion –username levin108

递归地把一个目录下的文件提交到版本库,这个目录提交上去后它里面并没有版本库信息,我觉得应该在执行完这条命令后就应该在所有的目录中创建.svn文件夹,以保存版本库信息的。

所以就只能再把版本库中的项目checkout下来,这样的话各目录中就有了版本控制信息了,就可以进行版本控制操作了。

svn blame
example:

$svn blame Makefile.am

2 levin108 SUBDIRS = src include skin resource
2 levin108
2 levin108 EXTRA_DIST = LICENSE LICENSE.OpenSSL
2 levin108
2 levin108 install: install-recursive
2 levin108 @echo “———————————————————-”;
2 levin108 @echo “| |”;
2 levin108 @echo “| OpenFetion 1.2 by lwp(levin108@gmail.com) |”;
2 levin108 @echo “| |”;
2 levin108 @echo “| OpenFetion a fetion client for linux based on GTK+2.0,|”;
2 levin108 @echo “| using Fetion Protocol Version 4. It supports most |”;
2 levin108 @echo “| useful functions of Mobile Fetion,more important. |”;
2 levin108 @echo “| It\`s small and fast,and is better in look. |”;
2 levin108 @echo “| More information at http://basiccoder.com/openfetion |”;
2 levin108 @echo “———————————————————-”;

显示指定文件(本地的或者远程版本库中的)作者和修订版本信息。 当然看到这个命令的输出的时候才发现原来版本控制软件真的很强大。

svn log
example

$ svn log
————————————————————————
r11 | levin108 | 2010-04-06 19:31:11 +0800 | 1 行
4.5
————————————————————————
r10 | levin108 | 2010-04-06 18:49:41 +0800 | 1 行
test
————————————————————————
r9 | levin108 | 2010-04-06 18:49:18 +0800 | 1 行

显示提交日志信息。

svn status

打印工作拷贝文件和目录的状态,如A,D,U…详细如下:

A 添加
D 删除
U 更新
C 冲突
G 合并

svn list
example:

$ svn list https://ofetion.googlecode.com/svn/trunk/ –username levin108
AUTHORS
COPYING
ChangeLog
INSTALL
LICENSE

列出版本库目录的条目

svn update
example:

$svn update -r7

用版本号为7的版本库项目更新你的本地项目副本,不加-r就默认用最新的版本更新,这个命令很重要。

常用的命令差不多就这些了,其它不常用的我也记不住了,写一下以后自己忘了可以过来查

分类: Linux 标签: ,

写了一个统计代码的小脚本

四月 1st, {2010 1 条评论 2,673 人阅读过  

没怎么写过脚本,想统计一下自己的代码,于是就简单写了个。

玩linux这么久了写过最多的脚本居然还是js,哈,以后得加强之方便的练习了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh
 
number=0
count()
{
	for file in *
	do
		if [ -d $file ]; then
			cd $file
			count
			cd ..
		elif echo $file | grep "\.[ch]$" > /dev/null; then
			pot=$(wc -l $file | cut -d" " -f1)
			number=`expr $number + $pot`
			echo $pot $file
		fi
	done
}
count
echo line total:$number

补充一下删除目录下所有隐藏的.swp文件(vi给生成的,vi不小心关闭的时候就会残留下来,烦死了)

1
find . -name "*.swp" -exec rm {} \;

分类: Linux 标签:

关于库文件的搜索路径问题

三月 29th, {2010 1 条评论 3,949 人阅读过  

项目需要用到sip协议,虽然以前折腾飞信的时候用的也是sip,但不是标准的sip,自己去写一套标准的sip协议栈既浪费时间,又没有什么意思,于是想到了osip和exosip。

装了osip和exosip这两个库,在linux下安装下来就非常简单了,典型的三步曲就可以搞定。

写了个小程序测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <eXosip2/eXosip.h>
#include <netinet/in.h>
 
int main(int argc , char* argv[])
{
	int i;
	int port = 5060;
	TRACE_INITIALIZE(6 , stdout);
 
	i = eXosip_init();
 
	if(i != 0)
		return -1;
	i = eXosip_listen_addr(IPPROTO_TCP , NULL , port , AF_INET , 0);
 
	if(i != 0 )
	{
		eXosip_quit();
		fprintf(stderr , "can not initialize transport layer");
		return -1;
	}
	return 0;
}

编译:gcc -o exosip exosip.c -leXosip2 -DENABLE_TRACE

编译通过了,执行./exosip的时候却会报错:

./exosip: error while loading shared libraries: libeXosip2.so.4: cannot open shared object file: No such file or directory

./exosip: error while loading shared libraries: libosipparser2.so.4: cannot open shared object file: No such file or directory

./exosip: error while loading shared libraries: libosip2.so.4: cannot open shared object file: No such file or directory

很显然,程序找不到需要的这三个共享库,查了一个/usr/lib和/lib这两个目录里面果然没有,再查了一个/usr/local/lib,果然是安装在了那里面,以往都会在编译时设置环境变量LD_LIBRARY_PATH或者直接在/usr/lib目录下创建相关库文件的符号链接,想想太麻烦了,干嘛不设置一下库文件的搜索路径。

库文件搜索路径是在/etc/ld.so.conf中定义的,只需要在最后面加上一行/usr/local/lib就可以了

实际上程序在运行时并不是通过检查这个文件来定位所需要的头文件的,而是通过/etc/ld.so.cache这个文件来定位的,这个文件并不是明文的文本文件,它是ldconfig命令通过检查/etc/ld.so.conf生成的缓存文件,如果通过检查ld.so.conf中的路径来搜索库文件,执行效率未免太低,于是就生成一个缓存文件,通过它来定位所需要库文件。

ld.so.conf修改完之后必须用ldconfig来更新ld.so.cache,否则ld.so.conf改了也没用,另外ldconfig命令需要用root权限执行。

分类: Linux 标签: , ,

Automake生成Makefile过程简介

二月 26th, {2010 1 条评论 3,740 人阅读过  

有校友在byr上看了我发的openfetion,发信息问我关于automake的东西,其实我了解的也并不多,只是自己查了些资料,然后借鉴了一下别人的项目中相关文件的写法,于是就想照着openfetion中的相关文件把自己对它的理解简单写一下,算是整理一下学过的知识,以后也好有个参考。
Automake支持三种目录层次:flat,shadow,deep
1.flat 所有的源文件及相关文件都放在顶层目录中。
2.shadow 主要的源文件存放在顶层目录中,其它的存放在各个子目录中。
3.deep 所有的源文件都分别存放在各个子目录中。

我的程序用了deep模式,所有的源文件都放在了src目录中。下面写一下automake生成Makefile的步骤:
1.运行autoscan命令,生成configure.scan。

configure.scan就是configure.in的模板,对它做一些修改,然后改名为configure.in或者configure.ac就可以了(新版本的automake好像是configure.ac)。
configure.in:

AC_INIT(src/openfetion.cpp)
AM_INIT_AUTOMAKE(openfetion,0.1)
AM_CONFIG_HEADER(config.h)
AM_PATH_GTK_2_0(,,AC_MSG_ERROR(openfetion 0.1 needs GTK+ 2.0))
AM_PATH_XML2(,,AC_MSG_ERROR(openfetion 0.1 needs LIBXML2))
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_OUTPUT(src/Makefile)
AC_INIT宏以任何一个源文件作为参数,它只是检查这个源文件的存在,也说意味着着源文件所在的目录存在
AM_INIT_AUTOMAKE 增加了几个标准的检查,它以程序名称和版本号作为参数
AC_PROG_CC 指出源代码可能是用C写的,如果源代码是用C++写的我们就需要AC_PROP_CXX
AC_PROG_INSTALL 会生成一个install目录文件,这样用户就可以通过输入“make install”来安装这个软件
AC_OUTPUT 指出将会生成的Makefile文件的名字
AC_CONFIG_HEADER 表示将会使用config.h文件,autoconf需要一个config.h.in文件,用它来生成config.h,config.h.in可以通过autoheader工具生成
AM_PATH_GTK_2_0(,,AC_MSG_ERROR(openfetion 0.1 needs GTK+ 2.0))
AM_PATH_XML2(,,AC_MSG_ERROR(openfetion 0.1 needs LIBXML2)) 这两句话检查系统中是否安装了程序所需要共享库, GTK+2.0和libxml2,这两个库在安装的时候分别安装了AM_PATH_GTK_2_0和 AM_PATH_XML2这两个宏,所以可以用这种方法检测,如果系统中没有安装libxml2,configure脚本就会执行失败,并报错:openfetion 0.1 needs LIBXML2
关于library的检查可参见文章:Using C/C++ libraries with Automake and Autoconf

其它的就不详细说了,需要的时候可以谷歌。
2.在顶层目录中创建一个Makefile.am,在其它各级需要的子目录中也创建Makefile.am。

我的顶层目录Makefile.am中只有下面几句话:

1
2
3
4
5
6
7
8
9
10
#子目录变量,用于递归处理各级子目录
SUBDIRS=src
#安装路径,可使用./configure --prefix=/usr/local/openfetion修改
prefix=/usr/local
#数据文件的安装路径
datadir=$(prefix)/skin
#数据文件的具体内容,这里的意思是要将skin目录下的所有文件安装到/usr/local/skin中
data_DATA=skin/* 
#程序打包时要加入的其它文件,使用make dist生成tar.gz文件时会放进去的东西
EXTRA_DIST=skin

src目录下的Makefile.am文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#libxml2 , GTK+2.0和GThread-2.0的cflags和libs
#libxml2安装了xml2-config脚本,GTK+2.0和GThread-2.0安装了.pc pkg-config文件
AM_CPPFLAGS=`xml2-config --cflags` `pkg-config --cflags gtk+-2.0 gthread-2.0`
AM_LDFLAGS=`xml2-config --libs` `pkg-config --libs gtk+-2.0 gthread-2.0`
#预定义的目录,prefix已经说过了
prefix=/usr/local
#这个是可执行文件安装的目录
bindir=$(prefix)/bin
#这个是自定义的目录,用来安装包含协议实现部分的静态库的
slibdir=/usr/lib
#编译生成可执行文件名称
bin_PROGRAMS=openfetion
#这里必须以上一步定义的名称为前缀,编译openfetion所需要的源文件
openfetion_SOURCES=openfetion.cpp  fetion_ui.cpp  ... login_ui.cpp
#编译openfetion所需要的库文件,libfx.a是我事先编译好了的。
openfetion_LDADD=libfx.a
#这个变量前面也说了,要把下面这些文件打包放到tar.gz中
EXTRA_DIST= 	   fetion_ui.h  main_ui.h  .... libfx.a
#要安装的头文件,执行完make install后,这些文件将被安装到/usr/include里面
include_HEADERS=   fgroup.h   flogin.h ... common.h
#自定义目录的数据文件,执行完make install后,这个文件就会被安装到/usr/lib里面
slib_DATA=libfx.a
3.生成GNU风格的项目时需要在顶层目录中你创建NEWS、 README、 ChangeLog 、AUTHOR这几个文件。
touch NEWS README ChangeLog AUTHOR
如果不需要生成GNU风格的项目就不需要创建这几个文件,而是需要在Makefile.am中加入
AUTOMAKE_OPTIONS = foreign
这是执行automake命令时的选项
4.执行aclocal。
由configure.in生成aclocal.m4
5.执行autoconf
由configure.in和aclocal.m4生成configure脚本
6.执行automake
由Makefile.am和configure.in生成各级目录下的Makefile.in
./configure执行的时候会扫描各个目录下的Makefile.in生成不同的Makefile。然后就可以执行make和make install了

GNU Automake工具集的功能远不止这些,我了解地也不够深刻,继续学习。

分类: Linux 标签: , , ,

Slackware安装配置

一月 30th, {2010 2 条评论 4,354 人阅读过  

前两天实验室新买了一台服务器,装系统的活就交给了我,一直钟爱于Slackware,于是就想着把服务器上也装一个Slackware,因为是台裸机,没办法就去买了张CD,刻了张Slackware13.0CD1,服务器也不需要图形界面之类的东西,一张CD就完全足够了,然后借了个USB光驱就开始安装了。
1.Slackware安装

第一次用CD安装,过程很顺利,其实也没有什么特别需要说的,就是按照提示一步一步来的,第一步是分区,服务器是1T 的硬盘,这么大的硬盘我还真不知道该怎么分区,留了200G以后以防以后需要装Windows,可能性极小,但还是留了。

我的分区方案是:

swap分区 4G
ext3 40G 挂载在/ 用于存放操作系统
ext3 10G 挂载在/tmp 临时目录,10G着实有点大,不过硬盘空间也实在是用不完
ext3 700G 挂载在/home 把剩下的磁盘空间全给了/home,这样每个人开一个账户,在上面怎么折腾都行
ntfs 200G 挂载在/winback 为将来的windows预留的,十有八九是用不到的

接下来的硬盘安装就很简单了,只不过没有Ubuntu等发行版那么好看的界面,安装起来也一样很方便,引导程序安装了Slackware默认的LILO

另外把我当时硬盘安装的过程也简单写一写:
下载了一个grub020p.zip,解压开后放到了C盘根目录下,然后修改boot.ini文件,在最后面加一句话:

C:\grldr="Start GRUB"

menu.lst改不改无所谓了,我是没改过,还是喜欢直接在grub下用C进入command提示符模式,自己输地几个命令。

然后把slackwarecd1,cd2解压到某分区根目录下,找到bzImage和initrd.img两个文件放到某目录下,注意一定要放在FAT32的分区下,貌似grub识别不了ntfs,没有fat32分区想要硬盘安装就麻烦了。

OK,重启之后就可以进入grub界面了,然后C键,输入下面命令:

grub>root (hd0 , 3)
grub>kernel /boot/bzImage
grub>initrd /boot/initrd.img
grub>setup

这样grub就把内核装进了内存,接下来的操作就跟光盘安装一样了,只不过在选择安装源的时候指定刚才解压的那两个CD的目录就可以了。

2.Slackware基本配置

实验室服务器配置就先暂时不说了,服务器暂时还没有特别的要求,既不做web服务器也不做ftp服务器,把ssh启了就可以了,sshd是默认启动的,所以装完之后我就懒得去管它了。

简单地说一下我自己的机器上的配置吧。slackware安装完成之后默认没有进入图形界面,可用命令startx进行图形界面,前提是安装了图形界面,slackware的六张cd里面,第一张是系统核心的东西,必须安装的,第二张里面有xfce4,第三张里有kde,我没装,剩下的三张没下下来,也不知道有什么,不过前两张cd就完全够用了。

slackware默认的运行级别是3,可以在修改/etc/inittab文件,将启动级别修改为4,则会自动进入图开界面。

ouclwp@darkstar:~$ sudo vi /etc/inittab
# Default runlevel. (Do not set to 0 or 6)
id:3:initdefault:
#将这句话中的3改成4就可以了,各级别的作用如下:
# These are the default runlevels in Slackware:
#   0 = halt
#   1 = single user mode
#   2 = unused (but configured the same as runlevel 3)
#   3 = multiuser mode (default Slackware runlevel)
#   4 = X11 with KDM/GDM/XDM (session managers)
#   5 = unused (but configured the same as runlevel 3)
#   6 = reboot

其实rc.4这个脚本所做的唯一工作是启动了X11 Session Manager,先检测gdm,然后是kdm,都找不到就启动xdm,如果不安装gnome和kde的话就会用xdm启动,xdm是很难看的,我安装了一个kdm,后来用着不爽,最后还是换成了gdm。

我在将kde换成gdm的时候出了一个问题,当时gdm没装好,而kdm已经被我删了,这时候运行级别4和startx都进不了xfce4图形界面,查看了一下/etc/X11/xinit里面的文件,发现xinitrc这个符号链接变成了红色,这也就意味着这个链接的源不见了,查看了一下确实是,它居然是链到xinitrc.kde的,这是我怎么也不能理解的,kde环境连同kdm一起早就被我给删了,xinitrc.kde也不在了,而且我也从来没用过kde,startx就是执行了xinitrc这上脚本,所以就会出问题,我把xinitrc重新连接到了xinitrc.xfce上就没问题了。

编码格式

编码格式刚开始是用的GBK,后来发现用GBK有诸多不便,从网络上读取数据的时候大多数的服务器软件都是用的UTF-8编码,取下来的数据都要通过程转换成GBK,非常麻烦,于是终于鼓起勇气把编码格式转换成了UTF-8。

ouclwp@darkstar:sudo vi /etc/profile.d/lang.sh
#修改下面两句话
export LANG=zh_CN #将系统汉化
export LC_CTYPE=zh_CN.UTF-8  #使用UTF-8做为编码格式

这样修改就可以了,当然从GBK迁移到UTF-8还要做很多修改,最麻烦的就是中文文件名乱码,可以写个脚本全部修改过来的,不过后来看看觉得也不多,就懒得写了,用下面的命令修改:

ouclwp@darkstar:convmv -f gbk -t utf8 --notest *

另外还有一些软件像gftp都要修改的,就不一一写出来了,gftp我已经不再用了,FileZilla我个人觉得是一款极为出色的FTP客户端软件,强烈推荐。

音乐播放器我用的是mocp(music on console),一个纯命令行的音乐播放器,非常漂亮。

中文字体我用的是Vera Sans YuanTi ,下载下来之后放到/usr/share/fonts里面,然后更新一下字体缓存就可以了

ouclwp@darkstar:/usr/share/fonts$ fc-cache -fv

其它的都没有什么值得说的了。个人觉得slackware是一个出色的发行版,而且特别适合做开发,它集成了很多常用的开发包,像libxml2,libpng,openssl等等,用起来非常方便。slackware虽然没有apt或者yum这样在线的包管理工具,但slackware的pkg包管理工具一样很出色,而且在slackbuild.org上可以下载到绝大多数常用的包,强烈推荐每一个coder或者developer使用slackware,它给我最直接的感觉就是简洁,高效,稳定。

分类: Linux 标签: ,