404频道

学习笔记

本实验为在虚拟机环境中实验,操作系统为Red Hat Enterprise6.0 32位,当前网卡列表如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@localhost ~]# ifconfig 
eth1 Link encap:Ethernet HWaddr 00:0C:29:8C:58:06
inet addr:192.168.124.140 Bcast:192.168.124.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe8c:5806/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:123 errors:0 dropped:0 overruns:0 frame:0
TX packets:57 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:18770 (18.3 KiB) TX bytes:11684 (11.4 KiB)
Interrupt:19 Base address:0x2024

eth2 Link encap:Ethernet HWaddr 00:50:56:3F:B3:90
inet addr:192.168.124.141 Bcast:192.168.124.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fe3f:b390/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:111 errors:0 dropped:0 overruns:0 frame:0
TX packets:43 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:16101 (15.7 KiB) TX bytes:10343 (10.1 KiB)
Interrupt:19 Base address:0x20a4

目的为将网卡eth1更改为eth0,将eth2更改为eth3。

修改grub.conf文件

在文件中内核启动时增加_biosdevname=0_选项。修改后的文件内容如下:

1
2
3
4
5
6
7
8
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Red Hat Enterprise Linux (2.6.32-71.el6.i686)
root (hd0,0)
kernel /vmlinuz-2.6.32-71.el6.i686 ro root=/dev/mapper/VolGroup-lv_root rd_LVM_LV=VolGroup/lv_root rd_LVM_LV=VolGroup/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM LANG=zh_CN.UTF-8 KEYBOARDTYPE=pc KEYTABLE=us nomodeset crashkernel=auto rhgb quiet biosdevname=0
initrd /initramfs-2.6.32-71.el6.i686.img

更改网卡配置文件内容和文件名称

在/etc/sysconfig/network-scripts目录中将原有的网卡配置文件ifcfg_Auto_eth1和ifcfg_Auto_eth2更改为ifcfg_eth0和ifcfg_eth3,同时修改文件的内容,将文件的内容中的网卡设备名称进行替换。替换后的文件ifcfg_eth0内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
TYPE=Ethernet
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=yes
IPV6INIT=no
NAME="Auto eth0"
UUID=995d037e-3b65-4490-a1fa-f26f6abf066d
ONBOOT=yes
HWADDR=00:0C:29:8C:58:06
PEERDNS=yes
PEERROUTES=yes
DEVICE=eth0

删除70-persistent-net.rules文件

该文件存在于/etc/udev/rules.d目录下。该文件如果不存在,开始时会自动创建,里面包含了网卡名称的配置信息。


在修改完上述内容后重新启动机器配置就修改过来了,修改完成之后的网卡配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@localhost rules.d]# ifconfig                                                                                                                  
eth0 Link encap:Ethernet HWaddr 00:0C:29:8C:58:06
inet addr:192.168.124.140 Bcast:192.168.124.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe8c:5806/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:87 errors:0 dropped:0 overruns:0 frame:0
TX packets:75 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:17174 (16.7 KiB) TX bytes:14520 (14.1 KiB)
Interrupt:19 Base address:0x2024

eth3 Link encap:Ethernet HWaddr 00:50:56:3F:B3:90
inet addr:192.168.124.141 Bcast:192.168.124.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fe3f:b390/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:72 errors:0 dropped:0 overruns:0 frame:0
TX packets:76 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:14164 (13.8 KiB) TX bytes:14955 (14.6 KiB)
Interrupt:19 Base address:0x20a4

[TOC]

# 安装kdevelop

确保可以上网,这里采用yum的安装方式进行安装。
首先执行命令:yum install kdevelop,会出现如下提示:

1
2
3
4
5
6
Loaded plugins: rhnplugin, security
This system is not registered with RHN.
RHN support will be disabled.
file:///mnt/file/rh5/Cluster/repodata/repomd.xml: [Errno 5] OSError: [Errno 2] 没有那个文件或目录: '/mnt/file/rh5/Cluster/repodata/repomd.xml'
Trying other mirror.
Error: Cannot retrieve repository metadata (repomd.xml) for repository: Cluster. Please verify its path and try again

出现上述错误是由于redhat没有注册,所有不能使用它自身的源进行更新,可以更换为CentOS系统的源进行更新,操作步骤为:
1、进入/etc/yum.repos.d/目录。在命令行输入:wget http://docs.linuxtone.org/soft/lemp/CentOS-Base.repo。
2、ls 一下,会看到一个文件名为CentOS-Base.repo的文件。
3、将原来的文件rhel-debuginfo.repo改名为rhel-debuginfo.repo.bak。
4、将CentOS-Base.repo改名为rhel-debuginfo.repo

再次运行命令:yum install kdevelop,就可以安装kdevelop了。

安装过程中遇到了需要的pcre包无法从centos的源中下载的问题,解决方法为根据yum命令无法下载的包,在google中搜索,下载包然后再redhat上用rpm的升级命令来安装。具体下载网址为:电子科技大学星辰工作室开源镜像服务

rpm相关命令:
安装一个包:rpm -ivh
升级一个包:rpm -Uvh
移走一个包:rpm -e

安装konsole

安装上kdevelop后在执行程序的时候会提示/bin/sh:konsole:command not found。执行yum install kdebase命令来安装konsole。

配置ssh服务

修改ssh服务的配置文件/etc/ssh/sshd_config文件,将文件中的#PasswordAuthentication yes注释打开。
修改ssh服务的配置文件/etc/ssh/sshd_config文件,将文件中的PermitRootLogin no更改为yes。这样即可以用ssh工具连接到该机器。

xmanager连接配置

该部分参考文档的网址为:http://blog.csdn.net/gltyi99/article/details/6141972

  1. 修改/usr/share/gdm/defaults.conf文件的权限,默认权限为444,chmod 700 /usr/share/gdm/defaults.conf。

  2. 在/usr/share/gdm/defaults.conf文件的末尾添加如下内容:

    1
    2
    3
    4
    5
    6
    Enable=true
    DisplaysPerHost=10
    Port=177
    AllowRoot=true
    AllowRemoteroot=true
    AllowRemoteAutoLogin=false
  3. 修改/etc/gdm/custom.conf文件

    1
    2
    [xdmcp]
    Enable=1
  4. 修改/etc/inittab文件,不修改原来的设置,在文件的最后增加一行:

    1
    x:5:respawn:/usr/sbin/gdm
  5. 修改/usr/share/gdm/defaults.conf文件,将其中的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [security]
    # Allow root to login. It makes sense to turn this off for kiosk use, when
    # you want to minimize the possibility of break in.
    AllowRoot=true
    # Allow login as root via XDMCP. This value will be overridden and set to
    # false if the /etc/default/login file exists and contains
    # "CONSOLE=/dev/login", and set to true if the /etc/default/login file exists
    # and contains any other value or no value for CONSOLE.
    AllowRemoteRoot=false
    # This will allow remote timed login.
    AllowRemoteAutoLogin=false
    # 0 is the most restrictive, 1 allows group write permissions, 2 allows all
    # write permissions.
    RelaxPermissions=0
    # Check if directories are owned by logon user. Set to false, if you have, for
    # example, home directories owned by some other user.
    CheckDirOwner=true
    # Number of seconds to wait after a failed login
    #RetryDelay=1
    # Maximum size of a file we wish to read. This makes it hard for a user to DoS
    # us by using a large file.
    #UserMaxFile=65536

    AllowRemoteRoot=false更改为AllowRemoteRoot=true。

  6. 修改/etc/securetty文件,在文件底部添加如下内容:

    1
    2
    3
    4
    5
    pts/0
    pts/1
    pts/2
    pts/3
    pts/4
  7. 修改/etc/pam.d/login文件,将其中的一行注释

    1
    #auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
  8. 修改/etc/pam.d/remote,将其中的一行注释

    1
    #auth       required     pam_securetty.so
  9. 修改/etc/xinetd.d/krb5-telnet文件,将文件内容由

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    service telnet
    {
    flags = REUSE
    socket_type = stream
    wait = no
    user = root
    server = /usr/kerberos/sbin/telnetd
    log_on_failure += USERID
    disable = yes
    }

    更改为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    service telnet
    {
    flags = REUSE
    socket_type = stream
    wait = no
    user = root
    server = /usr/kerberos/sbin/telnetd
    log_on_failure += USERID
    disable = no
    }

    同样将/etc/xinetd.d/ekrb5-telnet文件中的disable=yes更改为disable=no。

安装中文字体

为了阅读代码方便,安装字体。

  1. 将字体文件YaHei.Consolas.1.12.ttf放到Redhat的目录/usr/share/fonts/chinese/TrueType目录下
  2. 执行mkfontscale命令,重新生成fonts.scale文件
  3. 执行mkfontdir命令,重新生成了fonts.dir文件。
  4. 执行chkfontpath –add /usr/share/fonts/chinese/TrueType

更改操作系统编码从utf8到gb18030

可以通过locale命令来查看操作系统编码。输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LANG=zh_CN.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=

打开/etc/sysconfig/i18n文件,文件默认内容为:

1
LANG="zh_CN.UTF-8"

将文件内容修改为:

1
LANG="zh_CN.GBK"

相关下载

最适合程序员的字体:微软雅黑+Consolas

声明和定义

声明将一个名字引入到了程序中,;定义提供了一个实体(如类型、实例、函数)在程序中的唯一描述,为变量分配存储空间;

在一个给定的作用于中重复一个给定的声明是合法的,而重复定义是非法的。声明仅对当前编译单元有效,仅会在.o文件中加入了一个未定义符号。特定的类型不必与实际的定义类型匹配。

内部链接和外部链接

内部链接和外部链接是根据链接过程中一个符号是在编译单元内部还是外部进行划分的,编译单元是按照一个.c或.cpp文件的作用域进行划分的。

内部链接:一个标识符对于编译单元(一个目标文件)来说是局部的,并在链接时与其他编译单元中的标识符不冲突。

内部链接包括:

  • static类型的变量、函数
  • const类型的变量
  • 枚举类型的定义
  • typedef定义的类型
  • class、struct、union的定义
  • inline函数

外部链接:在多文件程序中,链接时这个标识符可以和其他编译单元交互。这些外部符号在程序中必须是唯一的,用来被其他编译单元中未定义的符号访问。

将带有外部链接的定义放在头文件中是错误的。

外部链接包括:

  • 类的非内联成员函数
  • 非内联且非static函数
  • 类的static数据成员

const类型的变量为内部链接的实例

test1.h内容如下:

1
void print1();

test1.cpp内容如下:

1
2
3
4
5
6
7
8
#include <stdio.h>

const int max_length = 256;

void print1()
{
printf("max_length=%d\n", max_length);
}

test2.h内容如下:

1
void print2();

test2.cpp内容如下:

1
2
3
4
5
6
7
8
#include <stdio.h>

const int max_length = 128;

void print2()
{
printf("max_length=%d\n", max_length);
}

main.cpp内容如下:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

#include "test1.h"
#include "test2.h"

int main()
{
print1();
print2();
return 1;
}

从实例可以看出在全局作用域内声明的const类型的变量为内部链接的,在多个文件的作用域中分别定义相同的const类型的变量并不会产生冲突。

基本规则

直接访问类的数据成员违反了面向对象中的封装原则,应该将类的数据成员私有化,并提供接口供部访问,类似于java bean规范。

避免使用全局变量,应该将全局变量封装到类中,并提供接口供外部访问。

为避免命名冲突,将全局函数封装到类中。

避免在头文件的作用域中使用enum、typedef和const数据,应该将这些数据封装到头文件的类作用域中。

在头文件中只应该包含如下内容:类、结构体、联合体和运算符函数的声明,类、结构体、联合体和内联函数的定义。

本文为Linux设备驱动程序的入门实践文章,编写一个hello world程序,并在Linux上执行。

编写驱动程序

驱动程序hello.c文件内容如下:

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
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");

int hello_init()
{
printk(KERN_WARNING "Hello kernel!\n");
return 0;
}


void hello_exit()
{
printk("Bye, kernel!\n");
}

module_init(hello_init);
module_exit(hello_exit)

编写Makefile

Makefile文件的写法可以采用传统的make方式,也可以采用kbuild的方式。

采用传统的make方式的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean
else
obj-m := hello.o
endif

采用kbuild方式的Makefile内容如下:

1
2
3
4
5
6
7
obj-m := hello.o

all :
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

编译

将hello.c和Makefile文件放在任意目录中,执行make命令编译。

安装

执行insmod hello.ko命令安装驱动程序,通过lsmod命令即可看到驱动程序已经安装。

通过查看/var/log/messages文件即可看到hello驱动程序打印的内容。

卸载

执行rmmod hello.ko命令即可卸载驱动程序模块。

参考文章

《深入理解Linux设备驱动程序》
《Linux那些事之我是USB》
Ubuntu12.10 内核源码外编译 linux模块–编译驱动模块的基本方法

本文仅为了练习Linux内核源码的编译安装,安装环境为VMWare下的CentOS,现有CentOS版本为2.6.32-358.el6.x86_64
/boot/grub/grub.conf文件内容如下:

1
2
3
4
5
6
7
8
9
# 注释部分去掉
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.32-358.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/vg_livedvd-lv_root rd_NO_LUKS rd_LVM_LV=vg_livedvd/lv_root rd_NO_MD crashkernel=auto rd_LVM_LV=vg_livedvd/lv_swap KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM LANG=zh_CN.UTF-8 rhgb quiet
initrd /initramfs-2.6.32-358.el6.x86_64.img

获取内核源码

首先从Linux的官方网站下载最新版内核Linux3.13。

执行tar Jxvf linux-3.13.tar.xz -C/usr/src/kernels命令将内核源码解压到内核源代码存放目录/usr/src/kernels/,该源码目录并不固定,但推荐将内核源码存放到该目录下。

为了将上次编译时的目标文件及相关设置文件删除,执行make mrproper

挑选功能

可以采用了多种方式,这里采用make menuconfig的方式来挑选内核功能,该方式不需要X Window(make xconfig方式)的支持,而且要比纯命令行方式(make config)要直观。执行make menuconfig遇到如下错误:

1
2
3
4
5
6
7
8
9
10
11
[root@localhost linux-3.13]# make menuconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
*** Unable to find the ncurses libraries or the
*** required header files.
*** 'make menuconfig' requires the ncurses libraries.
***
*** Install ncurses (ncurses-devel) and try again.
***
make[1]: *** [scripts/kconfig/dochecklxdialog] 错误 1
make: *** [menuconfig] 错误 2

这是因为需要ncurses库的支持,下面采用从源码安装的方式安装ncurses。

从ncurses的官方网站下载最新版的ncurses-5.9.tar.gz。然后分别执行./configure、makemake install`命令安装。

更改内核版本号标识

为了能够在编译完成后的内核版本中通过uname -r看到定义的内核版本号,修改Makefile文件。其中EXTRAVERSION字段值为空,将其赋值为kuring。

编译内核

执行make命令,该过程需要话费很长时间,我在512MB的VM下跑,花费了大约1个半小时时间。

编译内核模块

执行make modules命令。

安装内核模块

执行make modules_install命令,会将内核模块安装到/lib/modules目录下。

安装内核

执行make install命令,产生如下输出:

1
2
3
4
5
6
sh /usr/src/kernels/linux-3.13/arch/x86/boot/install.sh 3.13.0kuring arch/x86/boot/bzImage \
System.map "/boot"
ERROR: modinfo: could not find module vmhgfs
ERROR: modinfo: could not find module vsock
ERROR: modinfo: could not find module vmware_balloon
ERROR: modinfo: could not find module vmci

这个错误跟vmware的vmware tools有关,暂时不去管。

这样再去看/boot/grub/grub.conf文件,会看到文件已经变化,已经将新内核添加到开机启动项中。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 注释部分去掉
default=1
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (3.13.0kuring)
root (hd0,0)
kernel /vmlinuz-3.13.0kuring ro root=/dev/mapper/vg_livedvd-lv_root rd_NO_LUKS rd_LVM_LV=vg_livedvd/lv_root rd_NO_MD crashkernel=auto rd_LVM_LV=vg_livedvd/lv_swap KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM LANG=zh_CN.UTF-8 rhgb quiet
initrd /initramfs-3.13.0kuring.img
title CentOS (2.6.32-358.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/vg_livedvd-lv_root rd_NO_LUKS rd_LVM_LV=vg_livedvd/lv_root rd_NO_MD crashkernel=auto rd_LVM_LV=vg_livedvd/lv_swap KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM LANG=zh_CN.UTF-8 rhgb quiet
initrd /initramfs-2.6.32-358.el6.x86_64.img

同时在/boot目录下已经多出了vmlinuz-3.13.0kuring、System.map-3.13.0kuring、initramfs-3.13.0kuring.img文件。

重启系统后,在启动菜单中多出了新内核选项。进入新内核后,执行uname -r显示3.13.0kuring,说明新内核已经安装完成。

在用CentOS默认的svn客户端工具访问Windows下搭建的subversion时会提示如下错误:

1
2
[kuring@localhost 桌面]$ svn checkout https://192.168.100.100/svn/test
svn: 方法 OPTIONS 失败于 “https://192.168.100.100/svn/test: SSL handshake failed: SSL 错误:Key usage violation in certificate has been detected. (https://192.168.100.100)

通过执行如下命令可以看到svn是支持https协议的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[kuring@localhost ~]$ svn --version
svn,版本 1.6.11 (r934486)
编译于 Apr 11 2013,16:13:51

版权所有 (C) 2000-2009 CollabNet。
Subversion 是开放源代码软件,请参阅 http://subversion.tigris.org/ 站点。
此产品包含由 CollabNet(http://www.Collab.Net/) 开发的软件。

可使用以下的版本库访问模块:

* ra_neon : 通过 WebDAV 协议使用 neon 访问版本库的模块。
- 处理“http”方案
- 处理“https”方案
* ra_svn : 使用 svn 网络协议访问版本库的模块。 - 使用 Cyrus SASL 认证
- 处理“svn”方案
* ra_local : 访问本地磁盘的版本库模块。
- 处理“file”方案

这是由于svn客户端在https协议中使用了GnuTLS库造成的,将其更改为使用openssl库即可。通过执行如下命令可以查看svn使用的库:

1
2
3
[kuring@localhost bin]$ ldd svn | grep ssl
[kuring@localhost bin]$ ldd svn | grep tls
libgnutls.so.26 => /usr/lib64/libgnutls.so.26 (0x00007f33004ad000)

下面选择重新编译的方式来安装svn。

删除subversion

执行:yum remove subversion

检查openssl安装情况

这里已经安装:

1
2
3
[kuring@localhost tmp]$ rpm -qa | grep openssl
openssl-1.0.1e-15.el6.x86_64
openssl-devel-1.0.1e-15.el6.x86_64

安装neon

这里选择的安装版本为0.29.6,subversion对neon的版本有要求。如果不是subversion的版本,在执行subversion下的configure文件时并不会报错

1
2
3
4
5
[kuring@localhost software]$ tar zvxf neon-0.29.6.tar.gz
[kuring@localhost software]$ cd neon-0.29.6
./configure --with-ssl=openssl
make
make install

安装apr

1
2
3
4
5
tar zvxf apr-1.5.0.tar.gz
cd apr-1.5.0
./configure
make
make install

安装apr-util

1
2
3
4
5
tar zvxf apr-util-1.5.3.tar.gz 
cd apr-util-1.5.3
./configure --with-apr=/usr/local/apr
make
make install

下载sqllite

1
2
3
unzip sqlite-amalgamation-3080401.zip
mv sqlite-amalgamation-3080401 sqlite-amalgamation
mv sqlite-amalgamation subversion-1.8.8/ // 将其复制到subversion源码目录下

安装subversion

1
2
3
4
tar zvxf subversion-1.7.16.tar.gz
./configure --with-ssl --with-neon --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr
make
make install

然后再执行svn --version命令可以看到已经包含了https协议。

参考资料

SSL handshake failed: SSL error: Key usage violation in certificate has been detected CentOS

资料下载

需要的安装包下载

从官方网站下载最新的viplugin插件:viPlugin_2.12.0。

将viPlugin_2.12.0.zip文件解压到eclipse安装目录下的dropins目录下。

该插件为收费插件,在eclipse安装的根目录下新建viPlugin2.lic文件,文件内容为:_q1MHdGlxh7nCyn_FpHaVazxTdn1tajjeIABlcgJBc20
_。

重启eclipse后即可生效。

官方参考文档地址:http://www.viplugin.com/files/User_Manual_viPlugin.pdf


相关下载:viPlugin_2.12.0.zip

[TOC]

在Linux操作系统中,每个文件都有一组9个权限位来控制谁能够读写和执行该文件的内容。这组权限对于文件的意义非常容易理解。但是对于目录而言就不是那么容易理解了。要想搞明白权限机制需要了解文件系统中的inode节点和block等概念,并大致了解文件系统的内部实现原理。

文件的权限

这部分比较容易理解。比较容易搞错的为:

w位:包含对文件的添加、修改该文件内容的权限,但不包含删除文件或移动该文件的权限,因为文件的文件名信息存储在父目录的block中,而不是在该文件的inode节点中。父目录的block中包含该文件的inode节点和文件名信息,通过父目录中的inode节点找到该文件。

目录的权限

r位:表示具有读取该目录列表的权限。

w位:对该文件夹下创建新的文件或目录进行增加、删除、修改操作。

x位:这个稍微难以理解。表示用户能否进入该目录成为工作目录,即是否可以cd到该目录。通常和r位组合一块使用。

例子一

假设root用户对testing目录和testing目录下的testing文件拥有的如下权限:

1
2
3
[root@localhost tmp]# ls -ald testing/ testing/testing
drwxr--r--. 2 root root 4096 3月 1 11:44 testing/
-rw-------. 1 root root 0 3月 1 11:44 testing/testing

kuring用户拥有对该文件夹的读权限,但是没有x权限。当kuring用户访问时会提示如下内容:

1
2
3
4
5
6
7
8
9
// 拥有r的权限可以查询文件名,但是没有x权限,不能读取除文件名外的其他信息,产生了问号。
[kuring@localhost tmp]$ ll testing/
ls: 无法访问testing/testing: 权限不够
总用量 0
-????????? ? ? ? ? ? testing

// 没有x权限,不能进入该目录
[kuring@localhost tmp]$ cd testing/
bash: cd: testing/: 权限不够

例子二

在上述例子中,给kuring用户增加对目录testing的rwx权限,却只拥有testing目录下的testing文件的r权限。权限情况如下所示:

1
2
3
[kuring@localhost tmp]$ ls -ald testing testing/testing
drwxr--rwx. 2 root root 4096 3月 1 13:29 testing
-rw-r--r--. 1 root root 0 3月 1 13:29 testing/testing

kuring用户执行如下操作:

1
2
3
4
5
6
7
8
9
10
// 当对文件进行更改时由于没有对文件的w权限,操作失败
[kuring@localhost tmp]$ echo "world" >> testing/testing
bash: testing/testing: 权限不够

// 当对文件进行删除操作时却可以删除该文件,这是因为文件删除操作的权限是由该文件所在目录的w位决定的
// 文件删除操作会修改父目录中block节点中的文件名内容,而父目录的权限为rx,不可写。
[kuring@localhost tmp]$ rm testing/testing
rm:是否删除有写保护的普通文件 "testing/testing"?y
[kuring@localhost tmp]$ ls testing/
[kuring@localhost tmp]$

只有了解了原理,就可以理解在多级目录并且目录的权限不一致的情况下相应的权限问题了。


进程用户ID

要讲解set uid和set gid,就涉及到进程的用户ID概念。用户ID又可以分为两部分:

  • 实际用户ID和实际组ID:标识了究竟是哪个用户执行了该程序,跟命令行中的登录用户一致,可以通过id命令查看。

  • 有效用户ID和有效组ID:系统通过有效用户ID、有效组ID和附加组ID来决定进行对系统资源的访问权限。在Linux系统中一个用户可以属于多个组,在/etc/passwd文件中一个用户仅能标识出隶属于一个组ID,该组ID叫做默认的组ID。在/etc/group为文件中可以标识出一个用户隶属于多个组,这多个组中除去默认的组ID叫做附加组ID。

set uid

  • 该权限位仅对二进制文件有效
  • 执行者对该程序需要具有x的权限
  • 该权限仅在执行该程序过程中有效
  • 执行者将具有该程序拥有者的权限

以/usr/bin/passwd命令为例,该程序的权限为:rwsr-xr-x。普通用户可以调用该程序修改自己的密码,而密码文件/etc/shadow未设置任何权限,即只有root用户可以操作该文件。

1
2
3
4
[root@localhost tmp]# ll /usr/bin/passwd
-rwsr-xr-x. 1 root root 30768 2月 22 2012 /usr/bin/passwd
[root@localhost tmp]# ll /etc/shadow
----------. 1 root root 1248 11月 30 10:50 /etc/shadow

passwd文件的s标志表明setuid位被设置。

passwd的拥有者为root;当普通用户执行passwd命令时,普通用户具有该命令的执行权限;passwd执行该命令时会暂时获得root用户权限;/etc/shadow就可以被修改。

也许看到这里就会有疑问:那岂不是普通用户可以通过/etc/passwd命令修改其他用户的密码了。之所以不可以这么操作是因为passwd命令内部通过逻辑实现。

set gid

设置在文件上的情况:

  • 该权限位仅对二进制文件有效
  • 执行者对该程序需要具有x的权限
  • 执行者在运行程序的过程中将会获得该执行群组的权限

设置在目录上的情况:

  • 用户对目录具有r和x的权限
  • 用户在目录下的有效群组将会变成该目录的群组
  • 若用户在此目录下具有w的权限,使用者建立的群组与该目录的群组相同

粘附位(sticky bit)

该权限位仅对目录有效,如果在目录上设置了粘附位,只有该目录的属主、该文件的属主或root用户可以删除或重命名该目录文件。

/tmp文件夹的权限如下,其中的t位表示粘附位:

1
2
[kuring@localhost /]$ ll -ad tmp/
drwxrwxrwt. 25 root root 4096 3月 1 14:51 tmp/

如果在/tmp下kuring用户创建了自己的文件kuring_file,并设置权限为777,test用户并不能删除该文件

1
2
3
4
5
6
7
8
9
10
11
12
[kuring@localhost tmp]$ touch kuring_file
[kuring@localhost tmp]$ ll kuring_file
-rw-rw-r--. 1 kuring kuring 0 3月 1 15:05 kuring_file
[kuring@localhost tmp]$ chmod 777 kuring_file
[kuring@localhost tmp]$ ll kuring_file
-rwxrwxrwx. 1 kuring kuring 0 3月 1 15:05 kuring_file

[kuring@localhost tmp]$ su - test
密码:
[test@localhost ~]$ cd /tmp/
[test@localhost tmp]$ rm kuring_file
rm: 无法删除"kuring_file": 不允许的操作

表示方法

如果设置了setuid位,属主的执行权限中的x用s来代替;
如果设置了setgid位,组执行权限中的x用s来代替;
如果设置了sticky位,权限最后的那个字符被设置为t;
如果设置了setuid、setgid或sticky位中一个,又没有设置相应的执行位,这些位显示为S或T。

权限设定方式

4为setuid位,2为setgid位,1为sticky位。具体参考《鸟哥的Linux私房菜》。

参考文档

《鸟哥的Linux私房菜》
《UNIX/Linux系统管理技术手册》

在使用SSH或者telent远程登录到Linux 服务器,经常运行一些需要很长时间才能完成的任务,比如系统备份、ftp 传输等等。通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为它们执行的时间太长了。必须等待它们执行完毕,在此期间不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半途而废了。

安装

CentOS下默认没有安装该命令,从screen的官方网站下载,下载地址:http://ftp.gnu.org/gnu/screen/。

  1. 解压后执行./configure
  2. 执行make命令。在执行make命令时会遇到错误pty.c:38:26: 错误:sys/stropts.h:没有那个文件或目录,在/usr/install/sys/目录下创建一个stropts.h的空文件即可。
  3. 执行make install,该命令并不会将screen命令复制到系统的PATH变量包含的路径下,即不能执行screen命令。
  4. 执行install -m 644 etc/etcscreenrc /etc/screenrc
  5. 执行cp screen /bin/
  6. 执行cp doc/man/man1/screen.1 /usr/share/man/man1/,即可以可使用man screen查看帮助。

实现原理

当关闭窗口或断开连接时,内核会将SIGHUP信号发送到会话期首进程,进程对SIGHUP的处理动作为终止。如果会话期首进程终止,则该信号发送到该会话期前台进程组。一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。因此当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。

为解决上述问题,Linux程序在设计时可设计成守护进程的方式启动。

另外也可以通过nohup 命令 &的方式启动来解决问题。

新建screen

  • 直接输入screen命令即可使用。
  • 输入screen -S kuring,这里给screen取了一个名字,方便辨认。
  • screen 命令直接在screen中执行命令,命令结束后screen退出。

分离与恢复

在screen窗口中执行ctrl + a d命令,screen会给出_[detached]_提示,并恢复到执行screen之前的bash。
查找之前的screen执行screen -ls,会列出当前打开的screen。

1
2
3
4
There are screens on:
8576.pts-3.localhost (Attached)
8449.kuring (Detached)
2 Sockets in /tmp/uscreens/S-kuring.

这里系统中打开了两个screen,一个为Attached,另一个为Detached。

重新连接执行screen -r kuringscreen -r 8449screen -r,当系统中仅有一个处于Detached状态的screen时就可以直接执行screen -r命令。

关闭窗口

在screen的shell中执行exit命令即可关闭screen。

也可以执行ctrl + a k,会杀死当前screen中的所有运行进程。

错误

在screen中执行vi命令时会提示_E437: terminal capability “cm” required_错误,执行echo $TERM查看发现打印值为_screen_,而未执行screen时的bash打印值为_xterm_,在screen中执行export TERM=xterm即可解决该问题。

参考文档

更多高级使用方法请参考以下文档:

linux 技巧:使用 screen 管理你的远程会话
linux screen 命令详解

trim函数在其他语言中比较常见,这里用C语言实现一个,不使用C语言的库函数。该例子中不需要额外的申请空间,算法的时间复杂度为O(1)。

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
#include <stdio.h>

char *trim(char * str)
{
char *buf1, *buf2;
int i;
if (str == NULL)
{
return NULL;
}

// 处理字符串前面的空格
for (buf1=str; *buf1 && *buf1==' '; buf1++);

// 将去掉前面空格的字符串向前复制
for (buf2=str, i=0; *buf1;)
{
*buf2++ = *buf1++;
i++;
}
*buf2 = '\0';

// 处理字符串后面的空格
while (*--buf2 == ' ')
{
*buf2 = '\0';
}
return str;
}

int main(int argc, char *argv[])
{
printf("trim(\"%s\") ", argv[1]);
printf("returned \"%s\"\n", trim(argv[1]));
return 0;
}

0%