更新说明(2016-03-20)

文中的链接可能已经失效,GoAhead新的官网是
GoAhead
embedthis/goahead
最新的安装指南建议参考
Getting Started
Installation Overview

下载源码包并解压

1
2
3
4
5
6
7
8
9
[huzhifeng@fc15 ~]$ cd Downloads/
[huzhifeng@fc15 Downloads]$ mkdir goahead
[huzhifeng@fc15 Downloads]$ cd goahead/
[huzhifeng@fc15 goahead]$ wget http://data.goahead.com/Software/Webserver/2.5/webs-2-5.tar.gz
[huzhifeng@fc15 goahead]$ ls
webs-2-5.tar.gz
[huzhifeng@fc15 goahead]$ tar xzf webs-2-5.tar.gz
[huzhifeng@fc15 goahead]$ ls
webs-2-5 webs-2-5.tar.gz

进入源码根目录

1
2
3
4
5
6
[huzhifeng@fc15 goahead]$ cd webs-2-5
[huzhifeng@fc15 webs-2-5]$ ls
asp.c default.c ejlex.c form.c LYNX md5c.c misc.c readme.txt sock.c uemf.h url.c webrom.c webs.h WIN
balloc.c ECOS ejparse.c handler.c MACOSX md5.h NW ringq.c sockGen.c um.c utils webs.c websSSL.c wsIntrn.h
CE ej.h emfdb.c h.c matrixSSLSocket.c mime64.c page.c rom.c sym.c um.h value.c websda.c websSSL.h www
cgi.c ejIntrn.h emfdb.h LINUX matrixSSLSocket.h mime.c QNX4 security.c uemf.c umui.c VXWORKS websda.h websuemf.c wwwdemo

查看readme.txt,强烈建议看看wwwdemo/Webs25GettingStarted.pdf,里面详细介绍了如何编译配置,我一开始以为默认端口为80,输入地址总不能访问,其实在这个文档里就有说默认端口为8080

1
2
3
4
5
6
7
8
9
10
11
12
13
[huzhifeng@fc15 webs-2-5]$ cat readme.txt
Documentation is available in PDF format
Getting Started: wwwdemo/Webs25GettingStarted.pdf
Release notes: wwwdemo/Webs25ReleaseNotes.pdf
MatrixSSL Integration notes: wwwdemo/Webs25MatrixSSL.pdf
License and Legal: wwwdemo/license.pdf
Additional HTML documentation in wwwdemo and subfolders.
[huzhifeng@fc15 webs-2-5]$

阅读全文 »

内核中断程序

源码如下:

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
52
53
54
55
56
57
58
59
60
61
62
63
64
[huzhifeng@fc15 myirq]$ vi myirq.c
/*
Usage:
make
sudo insmod myirq.ko irq=19 devname=1119
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
static int irq;
static char* devname;
static struct tasklet_struct mytasklet;
module_param(irq,int,0644);
module_param(devname,charp,0644);
struct myirq
{
int devid;
};
struct myirq mydev={1119};
static void mytasklet_handler(unsigned long data)
{
printk("huzhifeng test:%s(),line %d,tasklet is wroking..\n", __FUNCTION__, __LINE__);
}
static irqreturn_t myirq_handler(int irq,void* dev)
{
struct myirq mydev;
static int count=0;
mydev=*(struct myirq*)dev;
printk("huzhifeng test:%s(),line %d,count=%d,devid=%d\n", __FUNCTION__, __LINE__, count, mydev.devid);
tasklet_init(&mytasklet,mytasklet_handler,0);
tasklet_schedule(&mytasklet);
count++;
return IRQ_HANDLED;
}
static int __init myirq_init()
{
printk("huzhifeng test:%s(),line %d,module init\n", __FUNCTION__, __LINE__);
if(request_irq(irq,myirq_handler,IRQF_SHARED,devname,&mydev)!=0)
{
printk("huzhifeng test:%s(),line %d,%s request IRQ:%d failed..\n", __FUNCTION__, __LINE__, devname, irq);
return -1;
}
printk("huzhifeng test:%s(),line %d,%s rquest IRQ:%d success..\n", __FUNCTION__, __LINE__, devname, irq);
return 0;
}
static void __exit myirq_exit()
{
printk("huzhifeng test:%s(),line %d,module exit\n", __FUNCTION__, __LINE__);
free_irq(irq,&mydev);
printk("huzhifeng test:%s(),line %d,%s free IRQ:%d success..\n", __FUNCTION__, __LINE__, devname, irq);
}
module_init(myirq_init);
module_exit(myirq_exit);
MODULE_LICENSE("GPL");

阅读全文 »

利用内核链表遍历进程

内核模块

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
[huzhifeng@fc15 klist]$ mkdir process_list
[huzhifeng@fc15 klist]$ cd process_list/
[huzhifeng@fc15 process_list]$ vi process_list.c
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/list.h>
4 #include <linux/sched.h> /* init_task */
5
6 MODULE_LICENSE("Dual BSD/GPL");
7
8 static int list_process_init(void)
9 {
10 struct task_struct *p = NULL, *task = NULL;
11 struct list_head *pos = NULL;
12 int count = 0;
13
14 printk(KERN_EMERG "%s(),line %d\n", __FUNCTION__, __LINE__);
15 task = &init_task;
16
17 list_for_each(pos, &task->tasks)
18 {
19 p = list_entry(pos, struct task_struct, tasks);
20 count++;
21 printk(KERN_EMERG "pid %d--->%s\n", p->pid, p->comm);
22 }
23
24 printk(KERN_EMERG "the number of process is %d\n", count);
25
26 return 0;
27 }
28
29 static void list_process_exit(void)
30 {
31 printk(KERN_EMERG "%s(),line %d\n", __FUNCTION__, __LINE__);
32 }
33
34 module_init(list_process_init);
35 module_exit(list_process_exit);
阅读全文 »

开发环境

本文是基于Fedora 15(FC15)搭建BOA webserver以及cgi环境
内核版本:

1
2
3
[huzhifeng@fc15 src]$ uname -a
Linux fc15 2.6.38.8-Zhifeng #1 SMP Wed Jun 22 22:19:59 CST 2011 i686 i686 i386 GNU/Linux
[huzhifeng@fc15 src]$

下载boa源码

最新版本是0.94.13

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[huzhifeng@fc15 Downloads]$ wget http://www.boa.org/boa-0.94.13.tar.gz
--2011-06-23 08:44:08-- http://www.boa.org/boa-0.94.13.tar.gz
Resolving www.boa.org... 192.203.178.67
Connecting to www.boa.org|192.203.178.67|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 122066 (119K) [application/x-tar]
Saving to: “boa-0.94.13.tar.gz”
100%[========================================================================================================>] 122,066 76.4K/s in 1.6s
2011-06-23 08:44:11 (76.4 KB/s) - “boa-0.94.13.tar.gz” saved [122066/122066]
[huzhifeng@fc15 Downloads]$ ls boa-0.94.13.tar.gz -l
-rw-rw-r--. 1 huzhifeng huzhifeng 122066 Jul 30 2002 boa-0.94.13.tar.gz

阅读全文 »

开发环境

Fedora 15,内核版本2.6.38.8

1
2
3
[huzhifeng@fc15 ~]$ uname -a
Linux fc15 2.6.38.8-Zhifeng #1 SMP Wed Jun 22 22:19:59 CST 2011 i686 i686 i386 GNU/Linux
[huzhifeng@fc15 ~]$

字符设备驱动程序

hzf-chrdev.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
#define MAJOR_NUM 222
static int hzf_var = 0;
static ssize_t hzf_read(struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
if(copy_to_user(buf, &hzf_var, sizeof(hzf_var)))
return -EFAULT;
return sizeof(hzf_var);
}
static ssize_t hzf_write(struct file *file, const char __user *buf,
size_t count, loff_t *offset)
{
if(copy_from_user(&hzf_var, buf, sizeof(int)))
return -EFAULT;
return sizeof(int);
}
static struct file_operations hzf_fops =
{
.owner = THIS_MODULE,
.read = hzf_read,
.write = hzf_write
};
static int __init hzf_init(void)
{
int ret = 0;
ret = register_chrdev(MAJOR_NUM, "hzfchar", &hzf_fops);
if(ret)
printk("register hzfchar fail");
else
printk("register success");
return 0;
}
static void __exit hzf_cleanup (void)
{
int ret = 0;
unregister_chrdev(MAJOR_NUM, "hzfchar");
if(ret)
printk("unregister hzfchar fail");
else
printk("unregister success");
}
module_init(hzf_init);
module_exit(hzf_cleanup);

阅读全文 »

printk分析

在内核开发时我们经常会用到printk调试,有时打印信息太多了,可以通过修改/proc/sys/kernel/printk文件内容来控制。

1
2
3
# cat /proc/sys/kernel/printk
7 4 1 7
#

该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。关于不同日志级别的更多信息,请查阅syslog(2)联机帮助。上面显示的4个数据分别对应:
控制台日志级别:优先级 高于该值的消息将被打印至控制台
默认的消息日志级别:将用该优先级来打印没有优先级的消息
最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
默认的控制台日志级别:控制台日志级别的缺省值
英文原版解释为:

/proc/sys/kernel/printk
The four values in this file are console_loglevel, default_message_loglevel, minimum_console_level and default_console_loglevel. These values influence printk() behavior when printing or logging error messages. See syslog(2) for more info on the different loglevels. Messages with a higher priority than console_loglevel will be printed to the console. Messages without an explicit priority will be printed with priority default_message_level. minimum_console_loglevel is the minimum (highest) value to which console_loglevel can be set. default_console_loglevel is the default value for console_loglevel.

阅读全文 »

示例代码

在内核模块中添加自己的定时器示例
首先,在文件顶部包含相关头文件和添加全局的定时器变量timer_huzhifeng

1
2
#include <linux/timer.h>
static struct timer_list timer_huzhifeng;

其次,在模块初始化的函数里添加定时器

1
2
3
4
5
6
7
8
9
10
static int __init my_timer_init(void)
{
...
timer_huzhifeng.data = (SYS_ULONG)pDev;
timer_huzhifeng.function = timer_huzhifeng_func;
init_timer(&timer_huzhifeng);
timer_huzhifeng.expires = RUN_AT(10*HZ);//10 second: #define RUN_AT(x) (jiffies + (x))
add_timer(&timer_huzhifeng);
...
}

在模块删除的的函数里移除定时器

1
2
3
4
5
6
static void __exit my_timer_exit(void)
{
……
del_timer_sync(&timer_huzhifeng);//or del_timer(&timer_huzhifeng);
……
}

定时器处理函数

1
2
3
4
5
6
7
static SYS_VOID timer_huzhifeng_func(SYS_ULONG data)
{
static int timer_count = 0;
timer_count++;
printk("huzhifengtest func=%s;line=%d;timer_count=%d\n", __FUNCTION__, __LINE__, timer_count);
mod_timer(&timer_huzhifeng, RUN_AT(10*HZ));
}

参考

linux内核定时器的用法

EOF

在Linux下删除SVN目录的方法有很多,以下是我常用的两种
方法一:
find . -type d -name ".svn" | xargs rm -rf 或者 find . -type d -iname ".svn" -exec rm -rf {} \;

方法二:

1
2
3
4
5
6
cat svn_clean.sh
for files in `tree -difa /path/to/your/dir | grep '.svn$'`
do
echo "Cleaning" $files " ... "
rm -rf $files
done

EOF

常用命令

删除一个词用dw
插入新行:o在当前行上,O在当前行下
替换:
:s/vivian/sky/ 替换当前行第一个 vivian 为 sky
:s/vivian/sky/g 替换当前行所有 vivian 为 sky
:n,$s/vivian/sky/ 替换第 n 行开始到最后一行中每一行的第一个 vivian 为 sky
:n,$s/vivian/sky/g 替换第 n 行开始到最后一行中每一行所有 vivian 为 sky
(n 为数字,若 n 为 .,表示从当前行开始到最后一行)
:%s/vivian/sky/(等同于 :g/vivian/s//sky/) 替换每一行的第一个 vivian 为 sky
:%s/vivian/sky/g(等同于 :g/vivian/s//sky/g) 替换每一行中所有 vivian 为 sky

显示行号

默认使用vim编辑源代码文件时不显示行号,需要在用户home目录下建一个.vimrc文件,追加一行代码set nu
如果你想对所有用户都这样,那么在/etc/vimrc(CentOS/Fedora系统)或者/etc/vim/vimrc(Debian/Ubuntu系统)文件中加入这一行(需要root权限)。
/etc/vimrc或者/etc/vim/vimrc是所有用户启动vim时都会执行的,每个用户的home目录下的.vimrc是这个用户启动vim时会执行的。
详细步骤如下:

1
2
3
4
5
6
7
8
9
[huzhifeng@srv ~]$ cd ~
[huzhifeng@srv ~]$ pwd
/home/huzhifeng
[huzhifeng@srv ~]$ vim .vimrc
set nu
~
~
".vimrc" [New] 1L, 7C written
[huzhifeng@srv ~]$

或者

1
[huzhifeng@srv ~]$ echo "set nu" >> ~/.vimrc

或者使用vim打开文件后:
显示行号执行:set nu"
取消显示行号执行:set nonu

复制/删除多行

在命令模式下按键5yy表示复制从当前行开始的5行内容,按p键粘贴, 按键5dd表示删除从当前行开始的5行内容

跳转到指定行

gg或者1G跳转到首行,G跳转到末尾行,#G跳转到第#行

TAB键设置

vim tab键默认4空格

1
2
3
4
5
vim ~/.vimrc
1 set ts=4
2 set sw=4
3 set expandtab
4 set autoindent

按tab键时产生的是4个空格,这种方式具有最好的兼容性。

EOF