Press "Enter" to skip to content

Tag: Linux Kernel

Linux内核参数设置sysctl命令详解

sysctl是一个允许您改变正在运行中的Linux系统的接口. 它包含一些 TCP/IP 堆栈和虚拟内存系统的高级选项, 这可以让有经验的管理员提高引人注目的系统性能. 用sysctl可以读取设置超过五百个系统变量. 基于这点, sysctl提供两个功能:读取和修改系统设置.

常用参数

-w  临时改变某个指定参数的值,如sysctl -w net.ipv4.ip_forward=1
-a  显示所有的系统参数
-p  从指定的文件加载系统参数,如不指定即从/etc/sysctl.conf中加载

以下是实例

$ sysctl -a     #查看所有可读变量

$ sysctl net.ipv4.ip_forward    #查看某个变量
net.ipv4.ip_forward = 1

$ sysctl -n net.ipv4.ip_forward    #获取某个变量的值
1

$ sysctl -w kernel.yama.ptrace_scope=0   #临时修改某个变量的当前值,即虚拟文件系统/proc下的值,重启失效
kernel.yama.ptrace_scope = 0

$ echo 1 > /proc/sys/net/ipv4/ip_forward  #临时修改某个变量的当前值,效果同上

#使用sed命令永久修改某值
#把kernel.yama.ptrace_scope开头的行修改为后面的值,注意第2个/后面有个c表示change
$ sudo sed -i "/^kernel.yama.ptrace_scope/ckernel.yama.ptrace_scope = 0" /etc/sysctl.d/10-ptrace.conf
$ sysctl -p    #将sysctl.conf文件中的修改读取到系统中,即虚拟文件系统/proc下的值
Leave a Comment

批量下载Linux Kernel版本,并对本地的Kernel进行比较

自己写的一个批量下载Kernel.org版本,并对本地的Kernel进行比较的脚本。记录一下吧。

自己部门6年前维护的一个kernel版本,只知道是基于kernel 2.6版本,却不知道是基于2.6.x版的。于是乎,写了这么个脚本,批量把2.6.x的所有版本全部下载回来,使用diff一一进行比对(导出到conclusion/diff-2.6.x-and-k2.txt文件中),并将所有版本的diff结果进行分析,再将分析数据导出到conclusion/all.txt中。

在conclusion/all.txt中,第一列是diff时官方的版本号,第二列是diff结果(conclusion/diff-2.6.x-and-k2.txt)的行数。重点在于第二列,这些数字中最小的那一个所对应的版本号,应该就是我部门维护的kernel的详细版本号了。

#!/bin/bash
for i in `seq 0 39`
do
    echo donwloading https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.$i.tar.bz2
    wget https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.$i.tar.bz2
    for a in `seq 1 57`
    do
        echo downloading https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.$i.$a.tar.bz2
        wget https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.$i.$a.tar.bz2
    done
done

if [ ! -d conclusion ]; then
    mkdir conclusion
fi

for file in `ls linux-2.6.*.tar.bz2`
do
    dirname=${file%.tar*}
    version=${dirname##*-}
    echo $dirname
    echo $version
    tar -jxvf $file
    diff -r $dirname k2_os-kernel-2.6.28.10 > conclusion/diff-$version-and-k2.txt
    rm -rf $dirname

    stat=`cat conclusion/diff-$version-and-k2.txt | wc -l`
    echo $version '        ' $stat >> conclusion/all.txt
done

count=`awk -F ' ' '{print $2}' conclusion/all.txt | sort -n | head -1`
version=`cat conclusion/all.txt | grep $count$ | awk -F ' ' '{print $1}' $line`
echo '' >> conclusion/all.txt
echo The shortest diff is $count, which kernel version is $version >> conclusion/all.txt
Leave a Comment

Linux编写内核模块实例

本文演示了Linux加载内核模块(驱动)的过程,文中实验环境为CentOS 5.9 64bit。

1,准备工作
安装基础软件包

yum install kernel-devel.x86_64 gcc.x86_64 gcc-c++.x86_64

然后会在/usr/src/kernels/下面安装好内核源码包,最好把目录的名字改一下,以便能够与/lib/modules/$(uname -r)/目录相响应,避免/lib/modules/$(uname -r)/目录中有一些软链接找不到内核源码包位置

mv /usr/src/kernels/2.6.* /usr/src/kernels/$(uname -r)-x86_64

2,加入内核模块(驱动)
进入字符设备驱动目录

[root@localhost ~]# cd /usr/src/kernels/$(uname -r)-x86_64/drivers/char
[root@localhost char]# mkdir mycdev    #建立驱动目录
[root@localhost char]# cd mycdev/
[root@localhost char]# cat /proc/devices   #找一个未使用的字符设备主设备号,比如199,记好
[root@localhost mycdev]# vim mycdev.c    #建立内核态设备驱动程序,内容见下方
[root@localhost mycdev]# vim Makefile    #建立Makefile文件,内容见下方
Leave a Comment

Linux内核调拭之printk用法(2)

本文演示了一下printk的基本用法,实验环境为CentOS 5.9 64bit

1,下载内核源码
下载地址是https://www.kernel.org/pub/linux/kernel/v2.6/
CentOS 5.9用的是2.6.18版,CentOS 6用的是2.6.32,下载对应版本的内核文件就可以了

# wget https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.18.tar.gz
# tar -zxvf linux-2.6.18.tar.gz
# cd linux-2.6.18

2,修改内核

vim init/main.c  

查找start_kernel,在大约456行有如下内容:
……
asmlinkage void __init start_kernel(void)
{
        char * command_line;
        extern struct kernel_param __start___param[], __stop___param[];

        smp_setup_processor_id();

        /*  
         * Need to run as early as possible, to initialize the
         * lockdep hash:
         */
        lockdep_init();
……

系统从start_kernel()函数开始启动。所以我们要把printk()添加到这个函数里

Leave a Comment

Linux内核调拭之printk用法

内核通过 printk() 输出相关信息,在调用 printk() 函数时必须要指定日志级别。

在 include/linux/kernel.h 中定义了如下几个日志级别

#define	KERN_EMERG	"<0>"	/* 系统崩溃 */
#define	KERN_ALERT	"<1>"	/* 必须紧急处理 */
#define	KERN_CRIT	"<2>"	/* 临界条件,严重的硬软件错误 */
#define	KERN_ERR	"<3>"	/* 报告错误 */
#define	KERN_WARNING	"<4>"	/* 警告 */
#define	KERN_NOTICE	"<5>"	/* 普通但还是须注意 */
#define	KERN_INFO	"<6>"	/* 信息 */
#define	KERN_DEBUG	"<7>"	/* 调试信息 */

这里也可以看出数值越小,其紧急和严重程度就越高。

printk()用法

printk(<2> "Hello, world!\n");          /* 直接用数字指定日志级别,用尖括号括起来 */
printk(KERN_ALERT "Hello, world!\n");   /* 也可以这么用 */
Leave a Comment

将驱动程序添加到Linux内核

一,概述
在linux内核中增加程序需要完成以下三项工作:
1.将编写的源代码复制到Linux内核源代码的相应目录
2.在目录的Kconfig文件中增加新源代码对应项目的编译配置选项
3.在目录的Makefile文件中增加对新源代码的编译条目

二,实例
1,把驱动代码usbtmc(文件夹)复制到/usr/src/linux-headers-2.6.32-31-generic/drivers/char下。
注意:
(1),设备驱动程序存放在内核源码树根目录drivers/的子目录下,在其内部,设备驱动文件进一步按照类别,类型等有序地组织起来。
a,字符设备存在于drivers/char/目录下
b,块设备存放在drivers/block/目录下
c,USB设备则存放在drivers/usb/目录下。
(2),此处的文件组织规则并非绝对不变,例如:USB设备也属于字符设备,也可以存放在drivers/usb/目录下。
(3),例如我们把驱动程序usbtmc(文件夹)存放在drivers/char/目录下,那么你要注意,在该目录下同时会存在大量的C源代码文件和许多其他目录。所有对于仅仅只有一两个源文件的设备驱动程序,可以直接存放在该目录下,但如果驱动程序包含许多源文件和其他辅助文件,那么可以创建一个新子目录。

Leave a Comment

Linux加载内核模块

Linux加载内核模块的过程,记录一下,主要命令有modprobe、insmod及depmod等,命令由module-init-tools的软件包提供,请先确认系统安装了此软件包。本文方法已在CentOS 5 x86_64和CentOS6 x86_64系统上验证通过。

一,查看内核已加载的模块

[root@os ~]# lsmod

该命令通过读取/proc/modules文件中的内容列出已加载的模块。
系统中的所有模块位于/lib/modules/$(uname -r)/kernel/下的各种目录中。

二,手动加载模块
手动加载模块的方法有两个,下面分别介绍。

2.1 执行insmod命令加载模块

[root@os ~]# insmod mycdev.ko

2.2 执行modprobe命令加载模块

将模块拷入到相应目录下
[root@os ~]# cp mycdev.ko /lib/modules/$(uname -r)/kernel/drivers/char/

然后把模块的绝对地址写入到modules.dep文件中
手动写入(注意写入的行末尾有一个冒号)
[root@os ~]# echo /lib/modules/$(uname -r)/kernel/drivers/char/mycdev.ko: >> /lib/modules/$(uname -r)/modules.dep
或者执行如下命令自动写入
[root@os ~]# depmod -a

然后,就可以加载模块了
[root@os ~]# modprobe mycdev        #加载模块
[root@os ~]# lsmod | grep mycdev    #检验加载是否成功
mycdev                 35840  0

三,卸载模块

[root@os ~]# rmmod sysdog

四,开机自动加载模块
鸟哥的linux私房菜一书中,介绍的Linux系统开机流程:
(1) 载入BIOS的硬件信息,并取得第一个开机装置的代号
(2) 读取第一个开机装置的MBR的boot Loader (grub)的开机信息
(3) 载入OS Kernel信息,解压Kernel,尝试驱动硬件
(4) Kernel执行init程序并获得run-lebel信息(如3或5)
(5) init执行/etc/rc.d/rc.sysinit
(6) 启动内核外挂模块(/etc/modprobe.conf)
(7) init执行run-level的各种Scripts,启动服务
(8) init执行/etc/rc.d/rc.local
(9) 执行/bin/login,等待用户Login
(10)Login后进入Shell

打开/etc/rc.sysinit(是一个软链接,指向/etc/rc.d/rc.sysinit),会发现有如下内容

……
# Load other user-defined modules
for file in /etc/sysconfig/modules/*.modules ; do
  [ -x $file ] && $file
done

# Load modules (for backward compatibility with VARs)
if [ -f /etc/rc.modules ]; then
        /etc/rc.modules
fi
……

由此可见,如果想让一个模块开机自动加载,只要把模块加到这两个文件之中即可。

[root@os ~]# echo 'modprobe mycdev' > /etc/sysconfig/modules/mycdev.modules
[root@os ~]# chmod +x /etc/sysconfig/modules/mycdev.modules #不能少,否则会加载失败

然后重启,执行lsmod命令,会发现模块已加载。

Leave a Comment