按日归档: 2007/04/07

快速编译Linux内核所需模块新方法

来自:linux.ccidnet.com

传统编译内核模块的方法繁琐而费时,本文将告诉我们一种快速编译所需要内核模块的新方法。当你安装完Linux系统,并且已经启动,恭喜你!如果你的硬盘上还安装了WinNT/2000系统,你试图去访问另一个NTFS分区时却遇到了麻烦。因为你所用的Linux系统没有已编译的支持NTFS文件系统的模块。怎么办?也许你会运行make menuconfig,重新定制你需要的所有模块,接着运行make modeules;make modeules_install来安装。这样不仅繁琐、费时,还可能会出现问题。或者因为编译内核对你有些棘手,太多的选择让你手足无措,你根本没有太好的方法。本文给你提供一个简单的方法,你可以轻松地去编译你所需要的支持NTFS系统的模块(ntfs.o)。以此为例,但愿对你编译其他模块有所帮助。

写此文时我用的系统是Red Hat Linux Release 7.0 (Guinness) Kernel 2.2.16-22 on an i686。从一个新安装的系统开始,我们一起去编译一个自己想要的支持NTFS文件系统模块。

一、找到编译内核所需要的.config文件

在/usr/src/linux/configs目录下有若干编译内核所用的配置。选择我们想要的配置,将它复制到/usr/src/linux目录下,改名为.config。

cp /usr/src/linux/configs/kernel-2.2.16-i686.config /usr/src/linux/.config

二、修改.config文件,去掉不用的模块,加上自己想要的模块

打开.config,有许多XXXX=m的项,这些都是要被编译为模块的项,因为我们不希望编译这些模块,所以要把XXXX=m的项统统去掉。然后再加上我们想要的模块,将# CONFIG_NTFS_FS is not set 改为CONFIG_NTFS_FS=m 当然,可以用你熟悉各种工具来做这件事。

三、编译NTFS模块

在/usr/src/linux目录下运行命令make modules来编译我们想要的NTFS模块。

四、安装NTFS模块

编译后得到的ntfs.o在/usr/src/linux/fs/ntfs目录下,手动将它复制到正确的目录下。

cp /usr/src/linux/fs/ntfs/ntfs.o /lib/modules/2.2.16-22/fs/

注意:千万不能运行命令make modules_install,否则将带来严重的后果,它会删除你系统中的所有模块,只安装刚刚编译的模块(ntfs.o)。

五、载入NTFS模块

运行命令depmod;modprobe ntfs 试着访问你的NTFS文件系统吧,祝你成功!

有些模块依赖于你的系统内核,所以不适用本文所提供的方法。还有些模块和其他模块有依赖关系。如果你不熟悉这些依赖关系的话,建议你在第二步去掉不用的模块选项后,通过make menuconfig来加上自己想要的模块。我用此方法用了三分钟编译了支持NTFS文件系统的模块,你呢?

Read: 558

建立一个带宽、线程可控的下载型WEB网站

http://www.chinaunix.net 作者:llzqq 发表于:2004-03-02 07:58:04

APACHE+MYSQL+PHP+PROFTPD+MOD_LIMITIP+MOD_BANDWIDTH

一、前言

本人结合网上资料和个人的实践,利用一个下午的时间写出了这个适用于资源下载型网站的典型配置。这种配置的WEB网站初步实现了IP线程和线程流量的管理,同时proftpd用于上传资源,ssh用于主机管理。无疑这样可以自己支配宝贵的网络带宽,文章后面有个简单的防火墙配置仅供参考,我用的linux版本是redhat as 3.0。希望大家在看了这篇文章后多多和我交流, MAIL:LLZQQ@163.COM

二、软件版本

apache-1.3.29
mysql-4.0.16
php-4.3.4
proftpd-1.2.9
mod_limitipconn-0.04
mod_bandwidth-2.0.4

三、安装配置Mysql

# cd mysql-4.0.16

# ./configure –prefix=/usr/local/mysql –localstatedir=/usr/local/mysql/data
–disable-maintainer-mode ?with-mysqld-user=mysql –enable-large-files-without-debug

# make
# make install

添加mysql用户

# /usr/sbin/groupadd mysql

Then we create a user called mysql which belongs to the mysql group;

# /usr/sbin/useradd -g mysql mysql

安装数据库文件:

#./scripts/mysql_install_db

设置文件权限:

# chown -R root:mysql /usr/local/mysql
# chown -R mysql:mysql /usr/local/mysql/data

配置ld.so.conf

# vi /etc/ld.so.conf

增加下面一句:

/usr/local/mysql/lib/mysql

建立mysql的启动文件:

# cp support-files/mysql.server /etc/init.d/mysql
# cp support-files/my-medium.cnf /etc/my.cnf

以安全模式启动mysql:

# /usr/local/mysql/bin/mysqld_safe ?user=mysql &

设置mysql的root密码:

# /usr/local/mysql/bin/mysqladmin -u root password new_password

把mysql服务设置为开机启动:

# chmod 755 /etc/init.d/mysql
# chkconfig ?-add mysql
# chkconfig mysql on

四、安装配置PHP

#cd php-4.3.4

#./configure –prefix=/usr/local/php –with-apxs=/usr/local/apache/bin/apxs –with-mysql=/usr/local/mysql

#make
#make install

建立php的配置文件:

# cp php.ini-dist /usr/local/php/lib/php.ini

修改php的配置文件:

#vi /usr/local/php/lib/php.ini

doc_root= “/home/www/”
file_uploads=Off
register-golbals = On

建立测试php页面

# vi /home/www/test.php

# chomd 755 /home/www/test.php

五、安装apache-1.3.29

# tar zvxf apache_1.3.29.tar.gz
# cd apache_1.3.29
# cp ../mod_bandwidth.c mod_bandwidth.c

修改src/include/httpd.h 增大最大线程数
# vi src/include/httpd.h

修改其中的
#define HARD_SERVER_LIMIT 256

#define HARD_SERVER_LIMIT 2560

# ./configure –prefix=/usr/local/apache –enable-module=so
–enable-module=rewrite –enable-shared=max
–htdocsdir=/home/www –add-module=mod_bandwidth.c
–permute-module=BEGIN:bandwidth

# make
# make install

建立启动文件:

#cp apachectl /etc/init.d/httpd

修改apache的配置文件:

#vi /usr/local/apache/conf/httpd.conf

修改、添加和确认存在下列配置项:

addDefaultCharset GB2312 注释掉“addDefaultCharset ISO8859*”
ExtendedStatus On
LoadModule php4_module modules/libphp4.so
DirectoryIndex index.html index.html.var index.php
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
LoadModule limitipconn_module libexec/mod_limitipconn.so
AddModule mod_limitipconn.c

安装mod_limitipconn-0.04

# tar xzf mod_limitipconn-0.04.tar.gz
# cd mod_limitipconn-0.04
# vi Makefile

APXS = /usr/local/apache/bin/apxs

# make
# make install

使用mod_limitip模块需要在httpd.conf中增加这个设置

设置要控制的目录
MaxConnPerIP 2 限制每个IP的最大线程数

完成mod_bandwidth模块的安装

创建 mod_bandwidth 运行需要的目录

mkdir /var/apachebw
mkdir /var/apachebw/link
mkdir /var/apachebw/master
chmod -R 777 /var/apachebw

修改httpd.conf增加下列内容

BandWidthDataDir "/var/apachebw/"
BandWidthModule on

BandWidth 192.168.0 0 200000 制局域网内用户的下载速度为200k
BandWidth all 51200 限制其他用户的下载速度为每秒 51200 字节

修改/etc/init.d/httpd

# vi /etc/init.d/httpd

在三行之后添加如下内容:
#!/bin/sh
#
# Startup script for the Apache Web Server
# chkconfig: – 85 15
# description: Apache is a World Wide Web server. It is used to serve
# HTML files and CGI.
# processname: httpd
# pidfile &: /usr/local/apache/log/httpd.pid
# config: /usr/local/apache/conf/httpd.conf

把apache服务设置为开机启动:

# chkconfig ?-add httpd
# chmod 755 /etc/init.d/httpd
# chkconfig httpd on

六、安装porftpd-1.2.9

# tar ?zxvf proftpd-1.2.9.tar.gz
# cd proftpd-1.2.9
# ./configure –prefix=/usr/local/proftpd
# make
# make install 

建立启动文件、把proftpd设置为开机启动

# cp ./contrib/dist/rpm/proftpd.init.d /etc/rc.d/init.d/proftpd

# chkconfig –add proftpd
# chmod 755 /etc/rc.d/init.d/proftpd

# vi /etc/rc.d/init.d/functions
export PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/proftpd/
sbin"

# vi /etc/rc.d/init.d/proftpd
config: /usr/local/proftpd/etc/proftpd.conf
PATH="$PATH:/usr/local/proftpd/sbin"

# chkconfig proftpd on

建立帐号和目录:

# mkdir /home/test
# chmod 755 /home/test
# adduser -d /home/test -g ftp -s /sbin/nologin test
# passwd test

# adduser -d /home/upload -g ftp -s /sbin/nologin upload
# passwd upload

配置/usr/local/proftpd/etc/proftpd.conf,禁用匿名登陆

ServerName "llzqq’s ftp service"
ServerType standalone
DefaultServer on

# Port 21 is the standard FTP port.
Port 21

# Umask 022 is a good standard umask to prevent new dirs and files
# from being group and world writable.
Umask 022

MaxInstances 10

# Set the user and group under which the server will run.
User nobody
Group ftp

# To cause every FTP user to be "jailed" (chrooted) into their home
# directory, uncomment this line.
DefaultRoot ~

# Normally, we want files to be overwriteable.

AllowOverwrite on

# We want ‘welcome.msg’ displayed at login, and ‘.message’ displayed
# in each newly chdired directory.
DisplayLogin welcome.msg
DisplayFirstChdir .message
RequireValidShell no

#Limit User of being enbled login ftp server

AllowGroup ftp
DenyAll

#

DenyGroup ftp

TransferRate RETR 51200 group ftp

DenyGroup ftp

TransferRate STOR 256000 group ftp

ServerIdent off
MaxClientsPerHost 2
TimeoutIdle 600
TimeoutLogin 300
TimeoutNoTransfer 300
TimeoutStalled 300

七、reboot计算机

# shutdown ?r now

打开浏览器输入:http://loaclhost/test.php

如果你看到了关于:mysql;apache;php的一大堆信息,恭喜,你的安装基本上成功了,下一步可以测试一下proftp和带宽的设置了。

八、建立一个简单有效的防火墙

export PATH=/sbin:/usr/sbin:/bin:/usr/bin

modprobe iptable_nat
modprobe ip_nat_ftp
modprobe ip_nat_irc
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc

echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 0 >/proc/sys/net/ipv4/conf/all/accept_source_route
echo 0 >/proc/sys/net/ipv4/conf/all/accept_redirects
echo 1 >/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 1 >/proc/sys/net/ipv4/conf/all/log_martians

iptables -F
iptables -X
iptables -Z

iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP

##
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

## Loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

## SYN-Flooding
iptables -N syn-flood
iptables -A INPUT -i eth0 -p tcp –syn -j syn-flood
iptables -A syn-flood -m limit –limit 1/s –limit-burst 4 -j RETURN
iptables -A syn-flood -j DROP

## Make sure that new TCP connections are SYN packets
iptables -A INPUT -i eth0 -p tcp ! –syn -m state –state NEW -j DROP

## HTTP
iptables -A INPUT -i eth0 -p tcp -d 0/0 –dport 80 -j ACCEPT

## IP packets limit
iptables -A INPUT -f -m limit –limit 100/s –limit-burst 100 -j ACCEPT
iptables -A INPUT -p icmp -m limit –limit 1/s –limit-burst 3 -j ACCEPT

## FTP service
iptables -A INPUT -i eth0 -p tcp –dport 21 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp –dport 20 -j ACCEPT

## SSH login
iptables -A INPUT -i eth0 -m mac –mac-source 00:00:00:00:00:00 -p tcp –dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp –dport 22 -j DROP

## Anything else not allowed
iptables -A INPUT -i eth0 -j DROP

九、附录:

mod_bandwidth选项简单说明:

BandWidthPulse
格式: BandWidthPulse <毫秒(千分之一秒>
默认: 1000
上下文: per server config

改变计算带宽的时间间隔,默认为1000毫秒(1秒)。使用更低的间隔可以获得
更精确的带宽控制,但消耗更多的CPU时间,反之亦然。

BandWidth
格式: BandWidth <速率>
默认: 无
上下文: per directory, .htaccess

限制这个目录下文件下载的速率。

domain 指定来自哪个域的连接受到这个设置的影响。
ip 指定来自哪个ip地址(或者ip段)的连接受到影响。
all 所有连接都受到影响。

示例:

# 来自 dualface.com 的连接不限制下载速度
BandWidth dualface.com 0
# 来自 192.168.0.0/16(或者192.168.0) 网段的连接不限制下载速度
BandWidth 192.168.0.0/16 0
# 其他连接限制下载速度为每秒1024字节
BandWidth all 1024
# 越前面的设置优先权越高

LargeFileLimit
格式: LargeFileLimit <文件大小> <速率>
默认: 无
上下文: per directory, .htaccess

对于超过指定大小的文件,下载时使用的速率。如果速率设置0即不限制速度,
但下载速度仍然要受到BandWidth设置的影响。如果设置成-1,则完全不受影响。
通过设置不同的文件大小和速率,可以设置不同大小范围内文件的下载速度。

示例:

文件尺寸大于等于200千字节的文件,下载速率为每秒3072字节
LargeFileLimit 200 3072
LargeFileLimit 1024 2048
MaxConnection
格式: MaxConnection <连接数>
默认: 0 (不限制)
上下文: per directory, .htaccess

当超过指定连接数时,拒绝新的连接。

MinBandWidth
格式: MinBandWidth <速率>
默认: all 256
上下文: per directory, .htaccess

设置最小带宽,默认为每秒256字节。根据BandWidth和LargeFileLimit设置的速
率。mod_bandwidth会计算允许的连接数。例如BandWidth为4096字节,而
MinBandWidth为1024字节,则最大并发连接数为4。

Mod_limitipconn选项简单说明:

设置要控制的目录
MaxConnPerIP 2 限制单IP并发连接数
NoIPLimit image/* 不受限制的文件类型

MaxConnPerIP 1
OnlyIPLimit audio/mpeg video 仅用于限制的文件类型

Read: 641

让MYSQL彻底支持中文

提要:系统自带的mysql默认字符集不是gbk,因此给数据库的推广应用以及中文程序的开发带来极大的不便,在没完没了的GBK和UTF8的转换过程中消耗了我们无数的精力以及系统的资源.经过摸索尝试解决了中文支持问题,经验与大家分享一下.

先将让slack支持中文,方法可以看"linuxsir.org 之Slackware讨论区",然后重新编译mysql,原来系统mysql的要先用卸载.
login:root

shell> removepkg mysql
shell> groupadd mysql
shell> cd /app
shell> mkdir mysql
shell> chmod 744 mysql
shell> useradd -G mysql -s /bin/bash –p /app/mysql mysql
shell> chown -R mysql.mysql mysql

下载mysql4.x.x

shell> gunzip < mysql-VERSION.tar.gz | tar -xvf -
shell> cd mysql-VERSION
shell> CFLAGS="-O3 -mcpu=pentium3"
CXX=gcc
XXFLAGS="-O3 -mcpu=pentium3 -felide-constructors"
./configure --prefix=/app/mysql
--with--charset=gbk
--with-extra-charsets="gbk gb2312 big5 utf8"
--with-unix-socket-path=/etc/mysql.sock
--enable-local-infile
--enable-thread-safe-client
--enable-assembler
--with-client-ldflags=-all-static
--with-mysqld-ldflags=-all-static

//-mcpu 根据CPU类型优化编译,可以让你的mysq表现更好!可选项目很多:i386, i486, i586, i686, pentium, pentium-mmx, pentiumpro, pentium2, pentium3, pentium4, k6, k6-2, k6-3, athlon, athlon-tbird, athlon-4, athlon-xp,athlon-mp,winchip-c6, winchip2 , c3.

shell> make
——————————————
错误时候
shell> make clean
再回上一步
————————————————————

shell> make install
shell> cp support-files/my-medium.cnf /etc/my.cnf
shell> cd /app/mysql
shell> bin/mysql_install_db --user=root
shell> chown -R root .
shell> chown -R mysql var
shell> chgrp -R mysql .
shell> ./bin/mysqld_safe --user=root --default-character-set=gbk &
shell> ./bin/mysqladmin -u root password 'new-password'
shell> ./bin/mysql -u root --default-character-set=gbk -p
mysql> status
...
Server characterset: gbk
Db characterset: gbk
Client characterset: gbk
Conn. characterset: gbk
....

看见characterset全是gbk就算成功了.
—————————————————————————————————-
在UTF8字符集的老数据库中,创建中文支持表脚本如下,对字段加上字符集说明

CREATE TABLE `test`.`cn` (
`zh` CHAR(10) CHARACTER SET gb2312 COLLATE gb2312_chinese_ci NOT NULL,
`中文` INT(11) NOT NULL
)
ENGINE = MYISAM;

注:CHARACTER SET 写GB2312 和gbk都可以,gbk优于gb2312.

对于新创建的数据库加个默认字符集声明GBK,就不用建表时候每个字段声明了,这样看起来简单流畅,没有特殊的痕迹,建议多采用这种方法.

mysql> CREATE DATABASE dbCN DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
CREATE TABLE `dbCN`.`cn` (
`zh` CHAR(10) NOT NULL,
`中文` INT(11) NOT NULL
)
ENGINE = MYISAM;
mysql> insert into cn values("真的?",1);

注:如果这些脚本用bin/mysql命令行是输入不了,可以 用mysql query Browser,或者编程执行.
——————————————————————————————————–

shell> bin/mysql -u root --default-character-set=gbk -p
mysql>use test
mysql> select * from cn;
+--------+------+
| zh | 中文 |
+--------+------+
| 真的?| 1 |
+--------+------+
1 row in set (0.00 sec)
---------------------------------------------

最后修改启动文件/etc/rc.d/rc.mysqld

改路径/app/mysql/bin/mysqld_safe
改路径/app/mysql/var/web.pid

/app/mysql/bin/mysqld_safe 后面加入 –user=root –default-character-set=gbk

原文链接:http://slack.linuxsir.org/main/?q=node/165

Read: 704

C中const的使用

基本解释

  const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。
虽然这听起来很简单,但实际上,const的使用也是c语言中一个比较微妙的地方,微妙在何处呢?请看下面几个问题。

问题:const变量 & 常量

为什么我象下面的例子一样用一个const变量来初始化数组,ANSI C的编译器会报告一个错误呢?

const int n = 5;
int a[n];

答案与分析:

1)、这个问题讨论的是“常量”与“只读变量”的区别。常量肯定是只读的,例如5, “abc”,等,肯定是只读的,因为程序中根本没有地方存放它的值,当然也就不能够去修改它。而“只读变量”则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符(Qualifier)。上述代码中变量n被修饰为只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时维度必须是“常量”,“只读变量”也是不可以的。

2)、注意:在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而const int n,n只是一个变量(常量 != 不可变的变量,但在标准C++中,这样定义的是一个常量,这种写法是对的),实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是ANSI C对数组的规定限制了它。

3)、那么,在ANSI C 语言中用什么来定义常量呢?答案是enum类型和#define宏,这两个都可以用来定义常量。

问题:const变量 & const 限定的内容

  下面的代码编译器会报一个错误,请问,哪一个语句是错误的呢?

typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;

答案与分析:

问题出在p2++上。

1)、const使用的基本形式: const char m;

限定m不可变。

2)、替换1式中的m, const char *pm;

限定*pm不可变,当然pm是可变的,因此问题中p1++是对的。

3)、替换1式char, const newType m;

限定m不可变,问题中的charptr就是一种新类型,因此问题中p2不可变,p2++是错误的。

问题:const变量 & 字符串常量

请问下面的代码有什么问题?

char *p = "i’m hungry!";
p[0]= ‘I’;

答案与分析

上面的代码可能会造成内存的非法写操作。分析如下, “i’m hungry”实质上是字符串常量,而常量往往被编译器放在只读的内存区,不可写。p初始指向这个只读的内存区,而p[0] = ‘I’则企图去写这个地方,编译器当然不会答应。

问题:const变量 & 字符串常量2

请问char a[3] = "abc" 合法吗?使用它有什么隐患?

答案与分析

在标准C中这是合法的,但是它的生存环境非常狭小;它定义一个大小为3的数组,初始化为“abc”,,注意,它没有通常的字符串终止符”,因此这个数组只是看起来像C语言中的字符串,实质上却不是,因此所有对字符串进行处理的函数,比如strcpy、printf等,都不能够被使用在这个假字符串上。

问题5:const & 指针

类型声明中const用来修饰一个常量,有如下两种写法,那么,请问,下面分别用const限定不可变的内容是什么?

1)、const在前面

const int nValue; //nValue是const
const char *pContent; //*pContent是const, pContent可变
const (char *) pContent;//pContent是const,*pContent可变
char* const pContent; //pContent是const,*pContent可变
const char* const pContent; //pContent和*pContent都是const

2)、const在后面,与上面的声明对等

int const nValue; // nValue是const
char const * pContent;// *pContent是const, pContent可变
(char *) const pContent;//pContent是const,*pContent可变
char* const pContent;// pContent是const,*pContent可变
char const* const pContent;// pContent和*pContent都是const

答案与分析:

const和指针一起使用是C语言中一个很常见的困惑之处,在实际开发中,特别是在看别人代码的时候,常常会因为这样而不好判断作者的意图,下面讲一下我的判断原则:

沿着*号划一条线,如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。你可以根据这个规则来看上面声明的实际意义,相信定会一目了然。

另外,需要注意:对于const (char *) ; 因为char *是一个整体,相当于一个类型(如 char),因此,这是限定指针是const。

另=======

const用于函数时出现三个位置:
例如:
const returnVal   function (const list_array)const;

形式不过如此
第一个const意思是:返回值是常量
第二个const意思是:函数过程中不能修改list_array的值
第三个const意思是:函数过程不能隐式的修改function参数的值

===

const char*, char const*, char*const的区别问题几乎是C++面试中每次都会有的题目。
事实上这个概念谁都有只是三种声明方式非常相似很容易记混。
Bjarne在他的The C++ Programming Language里面给出过一个助记的方法:
把一个声明从右向左读。
char * const cp; ( * 读成 pointer to )
cp is a const pointer to char
const char * p;
p is a pointer to const char;
char const * p;
同上因为C++里面没有const*的运算符,所以const只能属于前面的类型。

另:面定义的一个指向字符串的常量指针:
char * const prt1 = stringprt1;
其中,ptr1是一个常量指针。因此,下面赋值是非法的。
ptr1 = stringprt2;
而下面的赋值是合法的:
*ptr1 = "m";
因为指针ptr1所指向的变量是可以更新的,不可更新的是常量指针ptr1所指的方向(别的字符串)。
下面定义了一个指向字符串常量的指针:
const * ptr2 = stringprt1;
其中,ptr2是一个指向字符串常量的指针。ptr2所指向的字符串不能更新的,而ptr2是可以更新的。因此,
*ptr2 = "x";
是非法的,而:
ptr2 = stringptr2;
是合法的。
所以,在使用const修饰指针时,应该注意const的位置。定义一个指向字符串的指针常量和定义一个指向字符串常量的指针时,const修饰符的位置不同,前者const放在*和指针名之间,后者const放在类型说明符前。

Read: 725