??xml version="1.0" encoding="utf-8" standalone="yes"?> 名词解释Q?/strong>man epoll之后Q得到如下结果: NAME SYNOPSIS DESCRIPTION An epoll set is connected to a file descriptor created by epoll_cre- 其实Q一切的解释都是多余的,按照我目前的了解QEPOLL模型g只有一U格式,所以大家只要参考我下面的代码,p够对EPOLL有所了解了,代码的解释都已经在注释中Q?/p> while (TRUE) OnWriteEpoll (i);//查看当前的活动连接是否有需要写出的数据?br /> } 其实EPOLL的精华,按照我目前的理解Q也是上述的几D늟短的代码Q看来时代真的不同了Q以前如何接受大量用戯接的问题Q现在却被如此轻杄搞定Q真是让Z得不感叹?/p> 今天搞了一天的epollQ想做一个高q发的代理程序。刚开始真是郁?一直搞不通,|上也有几篇介绍epoll的文章。但都不深入Q没有将一些注意的地方讲明。以至于C很多弯\Q现自q一些理解共享给大家,以少走弯路? epoll_wait q行的原理是 {侍注册在epfd上的socket fd的事件的发生Q如果发生则发生的sokct fd和事件类型放入到events数组中? q且注册在epfd上的socket fd的事件类型给清空Q所以如果下一个@环你q要xq个socket fd的话Q则需要用epoll_ctl(epfd,EPOLL_CTL_MOD,listenfd,&ev)来重新设|socket fd的事件类型。这时不用EPOLL_CTL_ADD,因ؓsocket fdq未清空Q只是事件类型清I。这一步非帔R要?nbsp; 转: 今天被朋友问?#8220;Linux下可以替换运行中的程序么Q?#8221;Q以前依E记得Linux下是可以的(而Windows׃让)Q于是随口答?#8220;OK”。结果朋友发来一个执行结果:Qtest正在q行中) 看v来是E序被占用,无法覆盖。于是自己又再做了几个实验: Q?Q先rm删除正在q行的testQ然后cp test2 test没有错误了?br />Q?Q先mv改名正在q行的testQ然后cp test2 test也没有问题?/p> 查了查资料ƈ动手分析了一下,扑ֈ了比较满意的解释。cpq不改变目标文g的inodeQ事实上它的实现是这LQ?/p> 我原以ؓcp的实现是“rm + open(O_CREAT)”Q不q现在想想上面的实现方式才是最可靠的(保证了时序安全和目标文g的属性)。这也可以解释ؓ什么cp的目标文件会l承被覆盖文件的属性而非源文件?/p> Linux ׃Demand Paging机制的关p,必须保正在q行中的E序镜像Q注意,q文g本nQ不被意外修改,因此内核在启动程序后会锁定这个程序镜像的inode。这? 是ؓ什么cp在用“O_WRONLY|O_TRUNC”模式open目标文g时会p|。而先rm再cp的话Q新文g的inode其实已经改变了,? inodeq没有被真正删除Q直到内栔R攑֯它的引用。同理,mv只是改变了文件名Q其inode不变Q新文g使用了新的inode?/span> 问题到这里已l水落石出,不过刨根I底的个性驱使我再做了以下一l实验,没想到结果完全出乎我意料之外Q?/p> 写了一个简单的试E序Q?/p> foo()是另一个测试动态库libtest.so的导出接口,只打C行提C就q回。接下来我把上面Ҏ行文件的试用例对动态库又做了一遍: Q?Qcp libtest2.so libtest.so可以直接覆盖已加载的动态库?br />Q?Q先rm删除已加载的libtest.soQ然后cp libtest2.so libtest.so成功?br />Q?Q先mv改名已加载的libtest.soQ然后cp libtest2.so libtest.so成功?/p> 除了W一个用例外Q结果相同。这L来,动态库被加载时Nldq没有锁定inodeQ不q想想也可以宽恕Q毕竟ld也是用户态程序,没有权利去锁定inodeQ也不应与内核的文gpȝ底层实现耦合?/p> 到这里都q算在情理之中,看v来Linux也都处理的很好。不q还剩下一个问题:动态库被以cp的方式覆盖后N不会和Demand Paging机制产生冲突Q?/p> 在思考这个问题的q程中,我意识到前面q个试E序的一个致命漏z,E作修改如下Q?/p> q?ơ,再执行上面的三个用例后发玎ͼ“cp libtest2.so libtest.so”虽然仍可直接覆盖已加载的动态库Q但是测试程序马上出C“Segmentation fault”。而后两个用例l果不变。由此可见,惌安全的替换已加蝲的动态库Q还是用“W拙”?#8220;rm + cp”吧,看似捷径?#8220;cp覆盖”会直接葬送掉你的E序…… 看来Q我再一ơ低CLinux的健壮性,看似W合逻辑的流E也可能会带来灾 难性的后果Q?#8220;rm & cp”?#8220;cp覆盖”背后所隐藏的底层差异却可以成ؓ你的救星。Linux用得久是让h觉得q是一块充满了荆棘和陷q原始丛林Q只有步步ؓ营实t前 行才能走的更q?/p> 注:以上实验ZSuSE Linux Enterprise Server 9 SP1QLinux 2.6.5 & glibc 2.3.3Q?/p> 更改/etc/resolv.conf文g 如果你的linuxL只是在局域网内工作,请将nameserver地址改ؓ|卡本n的地址? 例: suselinux:~ # more /etc/resolv.conf nameserver 192.168.0.160 search site 然后重启|卡 suselinux:~ # ifconfig eth0 down suselinux:~ # ifconfig eth0 up W一qOMQ每个h都背负着一个沉重的十字Ӟ在缓慢而艰隑֜前行Q?/p>
途中Q有一个h忽然停了下来。他在想着什么! 他想Q上帝啊Q这个十字架太沉重了Q我可以把十字架砍掉一块! 于是他动手砍了v来! 砍掉之后走v来,的确是轻松了很多Q他的步伐也不由得加快了?/p>
p栯啊走啊!走着走着Q他觉得肩上的十字架q是很沉Q很重! 他祈求道Q上帝啊Q请你让我再砍掉一截吧Q我会走得更LQ?/p>
于是Q他又砍掉了一截! 感谢上帝Q这样一来,他感到轻村֤了! 如此Q他毫不费力地就走到了队伍的最前面。当其他人在吃力地负重前行时Q他却轻村֜Dv了小Ԍ 啊哈!谁料Q前边忽然出C一个又深又宽的沟壑Q沟上没有桥Q周围也没有路。也没有蜘蛛侠或者超人出来解救他… 后面的h都慢慢地赶上来了Q他们用自己背负的十字架搭在沟上Q做成桥Q从容不q地跨越了沟壑?/p>
他也惛_法炮制。只可惜啊,他的十字架之前已l被砍掉了长长的一大截Q根本无法做成桥帮助他跨沟壑! 于是Q当其他人都在朝着目标l箋前进Ӟ他却只能停在原地Q垂头气,q悔莫及…… ?
生的路上我们每个人都背负着各种各样的十字架在艰隑։行。它也许是我们的学习Q也许是我们的工作,也许是我们的感情。但是,正是q些责Q和义务,构成了我
们在q个世界上存在着的理由和价倹{所以,请不要埋怨学习的J重Q工作的劌Q感情的负担Q因为真正的快乐Q是奋战后的l果Q没有经历深ȝ痛苦Q我们也
׃会不到酣畅淋漓的快乐Q?/p>
每个人都背负着属于自己的十字架Q的是q样QOM的每个hQ都是背负着属于自己的十字架Q而当沟壑出现Ӟ他们也只能利用自p负的十字架去跨越沟壑Ql前q?/p>
所以:在h生的道\上,有些黑暗Q只能自q;有些痛苦Q只能自׃验;有些孤独Q也只能自己品尝……人生是没有捷径的Q?/p>
epoll - I/O event notification facility
#include <sys/epoll.h>
epoll is a variant of poll(2) that can be used either as Edge or Level
Triggered interface and scales well to large numbers of watched fds.
Three system calls are provided to set up and control an epoll set:
epoll_create(2), epoll_ctl(2), epoll_wait(2).
ate(2). Interest for certain file descriptors is then registered via
epoll_ctl(2). Finally, the actual wait is started by epoll_wait(2).
{
int nfds = epoll_wait (m_epoll_fd, m_events, MAX_EVENTS, EPOLL_TIME_OUT);//{待EPOLL旉的发生,相当于监听,至于相关的端口,需要在初始化EPOLL的时候绑定?br /> if (nfds <= 0)
continue;
m_bOnTimeChecking = FALSE;
G_CurTime = time(NULL);
for (int i=0; i<nfds; i++)
{
try
{
if (m_events[i].data.fd == m_listen_http_fd)//如果新监到一个HTTP用户q接到绑定的HTTP端口Q徏立新的连接。由于我们新采用了SOCKETq接Q所以基本没用?br /> {
OnAcceptHttpEpoll ();
}
else if (m_events[i].data.fd == m_listen_sock_fd)//如果新监到一个SOCKET用户q接Cl定的SOCKET端口Q徏立新的连接?br /> {
OnAcceptSockEpoll ();
}
else if (m_events[i].events & EPOLLIN)//如果是已l连接的用户Qƈ且收到数据,那么q行d?br /> {
OnReadEpoll (i);
}
catch (int)
{
PRINTF ("CATCH捕获错误/n");
continue;
}
}
m_bOnTimeChecking = TRUE;
OnTimer ();//q行一些定时的操作Q主要就是删除一些短U用L?br /> }
epoll用到的所有函数都是在头文件sys/epoll.h中声明,有什么地方不明白或函数忘C可以ȝ一下?
epoll和select相比Q最大不同在?
1epollq回时已l明的知道哪个sokcet fd发生了事Ӟ不用再一个个比对。这样就提高了效率?
2select的FD_SETSIZE是有限止的,而epoll是没有限止的只与pȝ资源有关?
1、epoll_create函数
函数声明Qint epoll_create(int size)
?函数生成一个epoll专用的文件描q符。它其实是在内核甌一I间Q用来存放你惛_注的socket fd上是否发生以及发生了什么事件。size是你在q个epoll fd上能x的最大socket fd数。随你定好了。只要你有空间。可参见上面与select之不?.
22、epoll_ctl函数
函数声明Qint epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
该函数用于控制某个epoll文g描述W上的事Ӟ可以注册事gQ修改事Ӟ删除事g?
参数Q?
epfdQ由 epoll_create 生成的epoll专用的文件描q符Q?
opQ要q行的操作例如注册事Ӟ可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD ?攏VEPOLL_CTL_DEL 删除
fdQ关联的文g描述W;
eventQ指向epoll_event的指针;
如果调用成功q回0,不成功返?1
用到的数据结?
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
如:
struct epoll_event ev;
//讄与要处理的事件相关的文g描述W?br />ev.data.fd=listenfd;
//讄要处理的事gcd
ev.events=EPOLLIN|EPOLLET;
//注册epoll事g
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
常用的事件类?
EPOLLIN Q表C对应的文g描述W可以读Q?br />EPOLLOUTQ表C对应的文g描述W可以写Q?br />EPOLLPRIQ表C对应的文g描述W有紧急的数据可读
EPOLLERRQ表C对应的文g描述W发生错误;
EPOLLHUPQ表C对应的文g描述W被挂断Q?br />EPOLLETQ表C对应的文g描述W有事g发生Q?br />
3、epoll_wait函数
函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
该函数用于轮询I/O事g的发生;
参数Q?br />epfd:由epoll_create 生成的epoll专用的文件描q符Q?br />epoll_event:用于回传代处理事件的数组Q?br />maxevents:每次能处理的事g敎ͼ
timeout:{待I/O事g发生的超时?单位我也不太清楚)Q?1相当于阻塞,0相当于非d。一般用-1卛_
q回发生事g数?br />
]]>
# cp test2 test
cp: cannot create regular file `test': Text file busy# strace cp test2 test 2>&1 | grep open.*test
open("test2", O_RDONLY|O_LARGEFILE) = 3
open("test", O_WRONLY|O_TRUNC|O_LARGEFILE) = 4#include <stdio.h>
int main(int argc, char * argv[])
{
foo(); // An export function by libtest.so.
sleep(1000);
return 0;
}#include <stdio.h>
int main(int argc, char * argv[])
{
loop:
foo(); // An export function by libtest.so.
sleep(1);
goto loop;
return 0;
}
]]>
]]>
2Q安装mysql++
3Q编译测试程?br />
#include "mysql++.h"
using namespace mysqlpp;
using namespace std;
int main()
{
//构造一个Connectioncȝ对象
Connection con(false);
const char* db = "mysql", *server = "127.0.0.1", *user = "pos", *pass = "pos";
if (con.connect(db, server, user, pass))
{
cout << "success" << endl;
string sql = "select * from users";
Query query = con.query(sql);
if (StoreQueryResult rs = query.store())
{
StoreQueryResult::const_iterator it;
for (it = rs.begin(); it != rs.end(); ++it)
{
Row row = *it;
cout << "/t" << row[0] << "/t" << row[1] << endl;
}
}
else
{
cerr << "Failed to get item list: " << endl;
return -1;
}
}
else
{
cout << "Failed to connect DB" << con.error() << endl;
return -1;
}
return 0;
}
4Q执?/test
如果报错?div>./test: error while loading shared libraries: libmysqlpp.so.3: cannot open shared object file: No such file or directory
5Q再ơ执行测试程?br />
]]>
.csyslog 3709 root 3u IPv4 59474 TCP 172.18.215.28:36097->216.83.44.226:81 (ESTABLISHED)
netstat -anp | grep 35236 查看端口对应的程?br />
ulimit 查看pȝ资源限制
查询q程占用资源情况Q如打开文g句柄
lsof -p q程?br />
strace -p q程?br />
]]>
#service vsftpd stop 停止
#service vsftpd restart 重启
3) 配置
主配|文?/etc/vsftpd/vsftpd.conf
用户控制文g /etc/vsftpd.ftpusers
实验一、设|Chroot——用户不能切换目?
因ؓ默认情况下是可以切换目录的,所以是很不安全的。?
1、限制所有用户不能切换目?
chroot_local_user=YES
2、设|指定的用户不能切换目录
chroot_local_user=NO
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list
实验二、用Vsftp.user_list讉K控制
利用/etc/vsftpd.user_list
A、设|在/etc/vsftpd.user_list文g中用户不能访问,其它用户可以讉K
userlist_enable=YES
userlist_deny=YES
userlist_file=/etc/vsftpd.user_list
B、设|在/etc/vsftpd.user_list文g中的用户能访问国Q其它用户不可以讉K?
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd.user_list
防止用户用ssh telnet{登?/strong>
vi /etc/passwd
ydzf:x:501:501::/home/ydzf:/bin/false
再修?etc/shells文gQ将/bin/falseq个文g加进?
]]>
select t.tablespace_name, round(sum(bytes/(1024*1024)),0) ts_size
from dba_tablespaces t, dba_data_files d
where t.tablespace_name = d.tablespace_name
group by t.tablespace_name;
2、查看表I间物理文g的名U及大小
select tablespace_name, file_id, file_name,
round(bytes/(1024*1024),0) total_space
from dba_data_files
order by tablespace_name;
3、查看回滚段名称及大?/p>
select segment_name, tablespace_name, r.status,
(initial_extent/1024) InitialExtent,(next_extent/1024) NextExtent,
max_extents, v.curext CurExtent
From dba_rollback_segs r, v$rollstat v
Where r.segment_id = v.usn(+)
order by segment_name ;
4、查看控制文?/p>
select name from v$controlfile;
5、查看日志文?/p>
select member from v$logfile;
6、查看表I间的用情?/p>
select sum(bytes)/(1024*1024) as free_space,tablespace_name
from dba_free_space
group by tablespace_name;
SELECT A.TABLESPACE_NAME,A.BYTES TOTAL,B.BYTES USED, C.BYTES FREE,
(B.BYTES*100)/A.BYTES "% USED",(C.BYTES*100)/A.BYTES "% FREE"
FROM SYS.SM$TS_AVAIL A,SYS.SM$TS_USED B,SYS.SM$TS_FREE C
WHERE A.TABLESPACE_NAME=B.TABLESPACE_NAME AND A.TABLESPACE_NAME=C.TABLESPACE_NAME;
7、查看数据库库对?/p>
select owner, object_type, status, count(*) count# from all_objects group by owner, object_type, status;
8、查看数据库的版本
Select version FROM Product_component_version
Where SUBSTR(PRODUCT,1,6)='Oracle';
9、查看数据库的创建日期和归档方式
Select Created, Log_Mode, Log_Mode From V$Database;
内容提要
使用下面?route 命o可以查看 Linux 内核路由表?
# route
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 * 255.255.255.0 U 0 0 0 eth0
169.254.0.0 * 255.255.0.0 U 0 0 0 eth0
default 192.168.0.1 0.0.0.0 UG 0 0 0 eth0
route 命o的输出项说明
输出? | 说明 |
---|---|
Destination | 目标|段或者主? |
Gateway | |关地址Q?#8221;*” 表示目标是本L所属的|络Q不需要\? |
Genmask | |络掩码 |
Flags | 标记。一些可能的标记如下Q? |
|
U ?路由是活动的 |
|
H ?目标是一个主? |
|
G ?路由指向|关 |
|
R ?恢复动态\׃生的表项 |
|
D ?p\q后台E序动态地安装 |
|
M ?p\q后台E序修改 |
|
! ?拒绝路由 |
Metric | 路由距离Q到达指定网l所需的中转数Qlinux 内核中没有用) |
Ref | 路由引用次敎ͼlinux 内核中没有用) |
Use | 此\由项被\pY件查扄ơ数 |
Iface | 该\p对应的输出接口 |
L路由是\由选择表中指向单个IP地址或主机名的\p录。主\qFlags字段为H。例如,在下面的CZ中,本地L通过IP地址192.168.1.1的\由器到达IP地址?0.0.0.10的主机?
Destination Gateway Genmask Flags Metric Ref Use Iface
----------- ------- ------- ----- ------ --- --- -----
10.0.0.10 192.168.1.1 255.255.255.255 UH 0 0 0 eth0
|络路由是代表主机可以到辄|络。网l\qFlags字段为N。例如,在下面的CZ中,本地L发送到|络192.19.12的数据包转发到IP地址?92.168.1.1的\由器?
Destination Gateway Genmask Flags Metric Ref Use Iface
----------- ------- ------- ----- ----- --- --- -----
192.19.12 192.168.1.1 255.255.255.0 UN 0 0 0 eth0
当主Z能在路由表中查找到目标主机的IP地址或网l\由时Q数据包p发送到默认路由Q默认网养I上。默认\qFlags字段为G。例如,在下面的CZ中,默认路由是IP地址?92.168.1.1的\由器?
Destination Gateway Genmask Flags Metric Ref Use Iface
----------- ------- ------- ----- ------ --- --- -----
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
讄和查看\p都可以用 route 命oQ设|内核\p的命令格式是Q?
# route [add|del] [-net|-host] target [netmask Nm] [gw Gw] [[dev] If]
其中Q?
dC机的路由
# route add -host 192.168.1.2 dev eth0:0
# route add -host 10.20.30.148 gw 10.20.30.40
d到网l的路由
# route add -net 10.20.30.40 netmask 255.255.255.248 eth0
# route add -net 10.20.30.48 netmask 255.255.255.248 gw 10.20.30.41
# route add -net 192.168.1.0/24 eth1
d默认路由
# route add default gw 192.168.1.1
删除路由
# route del -host 192.168.1.2 dev eth0:0
# route del -host 10.20.30.148 gw 10.20.30.40
# route del -net 10.20.30.40 netmask 255.255.255.248 eth0
# route del -net 10.20.30.48 netmask 255.255.255.248 gw 10.20.30.41
# route del -net 192.168.1.0/24 eth1
# route del default gw 192.168.1.1
?CentOS 中默认的内核配置已经包含了\由功能,但默认ƈ没有在系l启动时启用此功能。开?Linux 的\由功能可以通过调整内核的网l参数来实现。要配置和调整内核参数可以?sysctl 命o。例如:要开?Linux 内核的数据包转发功能可以使用如下的命令?
# sysctl -w net.ipv4.ip_forward=1
q样讄之后Q当前系l就能实现包转发Q但下次启动计算机时失效。ؓ了在下ơ启动计机时仍然有效,需要将下面的行写入配置文g/etc/sysctl.conf?
# vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
用户q可以用如下的命o查看当前pȝ是否支持包{发?
# sysctl net.ipv4.ip_forward