Linux下stdio.h调用系统的动态库查看:
编译:jackxiang@72.46.128.82:~/echo# gcc helo.c
说明调用的是:libc.so.6 这个动态库。
一、静态库的创建和使用:阅读全文
编译:jackxiang@72.46.128.82:~/echo# gcc helo.c
说明调用的是:libc.so.6 这个动态库。
一、静态库的创建和使用:阅读全文
今天没事写了个小demo, 根据域名获取http响应报文, 程序也不是很完善
其实主要是要练习一下非阻塞I/O处理.
上代码:
/*
* Author: looyao
*/
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
static int set_fl(int fd, int flags)
{
int val;
if ((val = fcntl(fd,F_GETFL,0)) < 0) {
printf("fcntl F_GETFL error\n");
return -1;
}
val |= flags;
if (fcntl(fd,F_SETFL,val) < 0) {
printf("fcntl F_SETFL error\n");
return -1;
}
return 0;
}
void timeout()
{
printf("time out\n");
exit(0);
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
struct hostent *host;
char *msg = strdup("GET / HTTP/1.1\r\nHOST: ");
char rbuf[32], res_header[1024];
char *host_ip, *ptr, *pos;
int ntowrite, nwrite, nread, nread_res_header = 0, content_length, nread_content_length = 0;
signal(SIGALRM, timeout);
if (argc < 2) {
printf("请输入域名参数\n");
exit(0);
} else if (argc > 2) {
printf("输入的参数过多\n");
exit(0);
}
msg = realloc(msg, strlen(msg) + strlen(argv[1]) + sizeof("\r\n\r\n"));
sprintf(msg + strlen(msg), "%s\r\n\r\n", argv[1]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(0);
}
host = gethostbyname(argv[1]);
if (host == NULL) {
printf("无法获取此域名IP\n");
goto END;
}
host_ip = inet_ntoa(*((struct in_addr *)host->h_addr));
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(80);
inet_pton(AF_INET, host_ip, &servaddr.sin_addr);
if( connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("connect");
exit(0);
}
if (set_fl(sockfd, O_NONBLOCK) < 0) {
printf("set nonblock error");
goto END;
}
ntowrite = strlen(msg);
ptr = msg;
alarm(10);
while (ntowrite > 0) {
nwrite = write(sockfd, ptr, ntowrite);
if (nwrite <= 0) {
perror("write:");
goto END;
}
ptr += nwrite;
ntowrite -= nwrite;
}
alarm(0);
/* read response header */
ptr = res_header;
alarm(10);
while (1) {
errno = 0;
nread = read(sockfd, ptr, sizeof(res_header) - nread_res_header);
if(nread < 0){
if(errno == EAGAIN){
continue;
}
perror("read");
goto END;
}
nread_res_header += nread;
ptr += nread;
if((pos = strstr(res_header, "\r\n\r\n")) != NULL || nread_res_header == sizeof(res_header)){
break;
}
}
alarm(0);
if (!(pos = strstr(res_header, "Content-Length:"))) {
printf("响应报文错误");
goto END;
} else {
pos += 16;
if (!(ptr = strstr(pos, "\r\n"))) {
printf("响应报文错误");
goto END;
}
char buf[10];
snprintf(buf, (ptr - pos) > 10 ? 10 : (ptr - pos) + 1, "%s", pos);
content_length = atoi(buf);
}
write(STDOUT_FILENO, res_header, nread_res_header);
if ((pos = strstr(ptr, "\r\n\r\n"))) {
pos += 4;
nread_content_length = nread_res_header - (pos - res_header);
} else {
/* 此处有bug, 如果响应头很长, 没有读到\r\n\r\n, 但是, 先这样吧 :D */
goto END;
}
alarm(10);
while (1) {
errno = 0;
memset(rbuf, 0, sizeof(rbuf));
nread = read(sockfd, rbuf, sizeof(rbuf));
if (nread < 0) {
if (errno == EAGAIN) {
continue;
}
perror("read");
goto END;
}
write(STDOUT_FILENO, rbuf, nread);
nread_content_length += nread;
if (nread_content_length >= content_length){
break;
}
}
alarm(0);
END:
close(sockfd);
free(msg);
return 0;
}
编译后运行 ./demo www.baidu.com
响应的报文如下:
HTTP/1.1 200 OK
Date: Thu, 29 Apr 2010 08:57:48 GMT
Server: BWS/1.0
Content-Length: 3521
Content-Type: text/html;charset=gb2312
Cache-Control: private
Expires: Thu, 29 Apr 2010 08:57:48 GMT
Set-Cookie: BAIDUID=4573491A3ED9E0B16CA37586CFB9460E:FG=1; expires=Thu, 29-Apr-40 08:57:48 GMT; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>百度一下,你就知道 </title><style>body{font:12px arial;text-align:center;background:#fff}body,p,form{margin:0;padding:0}body,form,#lg{position:relative}td{text-align:left}img{border:0}a{color:#00c}a:active{color:#f60}#u{padding:7px 10px 3px 0;text-align:right}#m{width:650px;margin:0 auto}#nv{font-size:16px;margin:0 0 4px -32px}#nv a,#nv b,#su,#lk{font-size:14px}#lg{margin:-17px 0 9px}#fm{padding-left:111px;text-align:left}#kw{width:391px;line-height:16px;padding:3px 1px;margin:0 6px 0 0;font:16px arial}#su{width:78px;height:28px;line-height:24px}#kw,#su{vertical-align:middle}#lk{margin:33px 0}#lk span{font:14px "宋体"}#lm{height:60px}#lh{margin:16px 0 5px;font:12px "宋体"}#lh a{font:12px arial}#hp{position:absolute;line-height:14px;margin:0 0 0 6px;top:-1px;*top:2px}#cp,#cp a{color:#77c}</style></head>
<body><p id="u"><a href="http://passport.baidu.com/?login&tpl=mn">登录</a></p><div id="m"><p id="lg"><img src="http://www.baidu.com/img/baidu_logo.gif" width="270" height="129" usemap="#mp"></p><p id="nv"><a href="http://news.baidu.com">新 闻</a> <b>网 页</b> <a href="http://tieba.baidu.com">贴 吧</a> <a href="http://zhidao.baidu.com">知 道</a> <a href="http://mp3.baidu.com">MP3</a> <a href="http://image.baidu.com">图 片</a> <a href="http://video.baidu.com">视 频</a> <a href="http://map.baidu.com">地 图</a></p><div id="fm"><form name="f" action="s"><input type="text" name="wd" id="kw" maxlength="100"><input type="submit" value="百度一下" id="su"><span id="hp"><a href="/gaoji/preferences.html">设置</a><br><a href="/gaoji/advanced.html">高级</a></span></form></div>
<p id="lk"><a href="http://hi.baidu.com">空间</a> <a href="http://baike.baidu.com">百科</a> <a href="http://www.hao123.com">hao123</a><span> | <a href="/more/">更多>></a></span></p><p id="lm"></p><p><a id="st" onClick="this.style.behavior='url(#default#homepage)';this.setHomePage('http://www.baidu.com')" href="http://utility.baidu.com/traf/click.php?id=215&url=http://www.baidu.com">把百度设为主页</a></p><p id="lh"><a href="http://e.baidu.com/?refer=888">加入百度推广</a> | <a href="http://top.baidu.com">搜索风云榜</a> | <a href="http://home.baidu.com">关于百度</a> | <a href="http://ir.baidu.com">About Baidu</a></p><p id="cp">©2010 Baidu <a href="/duty/">使用百度前必读</a> <a href="http://www.miibeian.gov.cn" target="_blank">京ICP证030173号</a> <img src="http://gimg.baidu.com/img/gs.gif"></p></div><map name="mp"><area shape="rect" coords="43,22,227,91" href="http://hi.baidu.com/baidu/" target="_blank" title="点此进入 百度的空间"></map></body>
<script>var w=window,d=document,n=navigator,k=d.f.wd,a=d.getElementById("nv").getElementsByTagName("a");if(n.userAgent.indexOf("MSIE")==-1||window.opera){d.getElementById("st").style.display="none"};for(var i=0;i<a.length;i++){a[i].onclick=function(){if(k.value.length>0){var o=this,h=o.href,q=encodeURIComponent(k.value);if(h.indexOf("q=")!=-1){o.href=h.replace(/q=[^&$]*/,"q="+q)}else{this.href+="?q="+q}}}};(function(){if(/q=([^&]+)/.test(location.search)){k.value=decodeURIComponent(RegExp.$1)}})();if(n.cookieEnabled&&!/sug?=0/.test(d.cookie)){d.write('<script src=http://www.baidu.com/js/bdsug.js?v=1.0.3.0><\/script>')};if(w.attachEvent){w.attachEvent("onload",function(){k.focus();})}else{w.addEventListener('load',function(){k.focus()},true)};w.onunload=function(){}</script></html><!--ae75535d4a224623-->
非阻塞要不断的轮询, 浪费了CPU时间, 但是说与使用select机制相比, 到底那个机制更快,
也需要看情况, 我会继续试验.
对于read的结束条件, 具体看通信的协议.
http协议主要是看Content-Length, 还有一种是Transfer-Encoding: chunked,
我这个小demo实现的是根据Content-Length判断read结束.
over, 未完待续...
来源:http://hi.baidu.com/teng0210/blog/item/4955e8946e992b47d0135e2a.html
C语言HTTP请求GET,因对《所谓黑客揭秘》,大家都攻击代码的要求。所以我开始了为期两周的C/C++学习。由于没有任何C/C++基础,而是临时突击,所以代码肯定漏洞甚多,请观者见谅。同时欢迎拍砖或者支出代码错误,以求大家共同进步。:
来自:http://blog.csdn.net/aofengdaxia/article/details/5984431
其实主要是要练习一下非阻塞I/O处理.
上代码:
/*
* Author: looyao
*/
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
static int set_fl(int fd, int flags)
{
int val;
if ((val = fcntl(fd,F_GETFL,0)) < 0) {
printf("fcntl F_GETFL error\n");
return -1;
}
val |= flags;
if (fcntl(fd,F_SETFL,val) < 0) {
printf("fcntl F_SETFL error\n");
return -1;
}
return 0;
}
void timeout()
{
printf("time out\n");
exit(0);
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
struct hostent *host;
char *msg = strdup("GET / HTTP/1.1\r\nHOST: ");
char rbuf[32], res_header[1024];
char *host_ip, *ptr, *pos;
int ntowrite, nwrite, nread, nread_res_header = 0, content_length, nread_content_length = 0;
signal(SIGALRM, timeout);
if (argc < 2) {
printf("请输入域名参数\n");
exit(0);
} else if (argc > 2) {
printf("输入的参数过多\n");
exit(0);
}
msg = realloc(msg, strlen(msg) + strlen(argv[1]) + sizeof("\r\n\r\n"));
sprintf(msg + strlen(msg), "%s\r\n\r\n", argv[1]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(0);
}
host = gethostbyname(argv[1]);
if (host == NULL) {
printf("无法获取此域名IP\n");
goto END;
}
host_ip = inet_ntoa(*((struct in_addr *)host->h_addr));
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(80);
inet_pton(AF_INET, host_ip, &servaddr.sin_addr);
if( connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("connect");
exit(0);
}
if (set_fl(sockfd, O_NONBLOCK) < 0) {
printf("set nonblock error");
goto END;
}
ntowrite = strlen(msg);
ptr = msg;
alarm(10);
while (ntowrite > 0) {
nwrite = write(sockfd, ptr, ntowrite);
if (nwrite <= 0) {
perror("write:");
goto END;
}
ptr += nwrite;
ntowrite -= nwrite;
}
alarm(0);
/* read response header */
ptr = res_header;
alarm(10);
while (1) {
errno = 0;
nread = read(sockfd, ptr, sizeof(res_header) - nread_res_header);
if(nread < 0){
if(errno == EAGAIN){
continue;
}
perror("read");
goto END;
}
nread_res_header += nread;
ptr += nread;
if((pos = strstr(res_header, "\r\n\r\n")) != NULL || nread_res_header == sizeof(res_header)){
break;
}
}
alarm(0);
if (!(pos = strstr(res_header, "Content-Length:"))) {
printf("响应报文错误");
goto END;
} else {
pos += 16;
if (!(ptr = strstr(pos, "\r\n"))) {
printf("响应报文错误");
goto END;
}
char buf[10];
snprintf(buf, (ptr - pos) > 10 ? 10 : (ptr - pos) + 1, "%s", pos);
content_length = atoi(buf);
}
write(STDOUT_FILENO, res_header, nread_res_header);
if ((pos = strstr(ptr, "\r\n\r\n"))) {
pos += 4;
nread_content_length = nread_res_header - (pos - res_header);
} else {
/* 此处有bug, 如果响应头很长, 没有读到\r\n\r\n, 但是, 先这样吧 :D */
goto END;
}
alarm(10);
while (1) {
errno = 0;
memset(rbuf, 0, sizeof(rbuf));
nread = read(sockfd, rbuf, sizeof(rbuf));
if (nread < 0) {
if (errno == EAGAIN) {
continue;
}
perror("read");
goto END;
}
write(STDOUT_FILENO, rbuf, nread);
nread_content_length += nread;
if (nread_content_length >= content_length){
break;
}
}
alarm(0);
END:
close(sockfd);
free(msg);
return 0;
}
编译后运行 ./demo www.baidu.com
响应的报文如下:
HTTP/1.1 200 OK
Date: Thu, 29 Apr 2010 08:57:48 GMT
Server: BWS/1.0
Content-Length: 3521
Content-Type: text/html;charset=gb2312
Cache-Control: private
Expires: Thu, 29 Apr 2010 08:57:48 GMT
Set-Cookie: BAIDUID=4573491A3ED9E0B16CA37586CFB9460E:FG=1; expires=Thu, 29-Apr-40 08:57:48 GMT; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>百度一下,你就知道 </title><style>body{font:12px arial;text-align:center;background:#fff}body,p,form{margin:0;padding:0}body,form,#lg{position:relative}td{text-align:left}img{border:0}a{color:#00c}a:active{color:#f60}#u{padding:7px 10px 3px 0;text-align:right}#m{width:650px;margin:0 auto}#nv{font-size:16px;margin:0 0 4px -32px}#nv a,#nv b,#su,#lk{font-size:14px}#lg{margin:-17px 0 9px}#fm{padding-left:111px;text-align:left}#kw{width:391px;line-height:16px;padding:3px 1px;margin:0 6px 0 0;font:16px arial}#su{width:78px;height:28px;line-height:24px}#kw,#su{vertical-align:middle}#lk{margin:33px 0}#lk span{font:14px "宋体"}#lm{height:60px}#lh{margin:16px 0 5px;font:12px "宋体"}#lh a{font:12px arial}#hp{position:absolute;line-height:14px;margin:0 0 0 6px;top:-1px;*top:2px}#cp,#cp a{color:#77c}</style></head>
<body><p id="u"><a href="http://passport.baidu.com/?login&tpl=mn">登录</a></p><div id="m"><p id="lg"><img src="http://www.baidu.com/img/baidu_logo.gif" width="270" height="129" usemap="#mp"></p><p id="nv"><a href="http://news.baidu.com">新 闻</a> <b>网 页</b> <a href="http://tieba.baidu.com">贴 吧</a> <a href="http://zhidao.baidu.com">知 道</a> <a href="http://mp3.baidu.com">MP3</a> <a href="http://image.baidu.com">图 片</a> <a href="http://video.baidu.com">视 频</a> <a href="http://map.baidu.com">地 图</a></p><div id="fm"><form name="f" action="s"><input type="text" name="wd" id="kw" maxlength="100"><input type="submit" value="百度一下" id="su"><span id="hp"><a href="/gaoji/preferences.html">设置</a><br><a href="/gaoji/advanced.html">高级</a></span></form></div>
<p id="lk"><a href="http://hi.baidu.com">空间</a> <a href="http://baike.baidu.com">百科</a> <a href="http://www.hao123.com">hao123</a><span> | <a href="/more/">更多>></a></span></p><p id="lm"></p><p><a id="st" onClick="this.style.behavior='url(#default#homepage)';this.setHomePage('http://www.baidu.com')" href="http://utility.baidu.com/traf/click.php?id=215&url=http://www.baidu.com">把百度设为主页</a></p><p id="lh"><a href="http://e.baidu.com/?refer=888">加入百度推广</a> | <a href="http://top.baidu.com">搜索风云榜</a> | <a href="http://home.baidu.com">关于百度</a> | <a href="http://ir.baidu.com">About Baidu</a></p><p id="cp">©2010 Baidu <a href="/duty/">使用百度前必读</a> <a href="http://www.miibeian.gov.cn" target="_blank">京ICP证030173号</a> <img src="http://gimg.baidu.com/img/gs.gif"></p></div><map name="mp"><area shape="rect" coords="43,22,227,91" href="http://hi.baidu.com/baidu/" target="_blank" title="点此进入 百度的空间"></map></body>
<script>var w=window,d=document,n=navigator,k=d.f.wd,a=d.getElementById("nv").getElementsByTagName("a");if(n.userAgent.indexOf("MSIE")==-1||window.opera){d.getElementById("st").style.display="none"};for(var i=0;i<a.length;i++){a[i].onclick=function(){if(k.value.length>0){var o=this,h=o.href,q=encodeURIComponent(k.value);if(h.indexOf("q=")!=-1){o.href=h.replace(/q=[^&$]*/,"q="+q)}else{this.href+="?q="+q}}}};(function(){if(/q=([^&]+)/.test(location.search)){k.value=decodeURIComponent(RegExp.$1)}})();if(n.cookieEnabled&&!/sug?=0/.test(d.cookie)){d.write('<script src=http://www.baidu.com/js/bdsug.js?v=1.0.3.0><\/script>')};if(w.attachEvent){w.attachEvent("onload",function(){k.focus();})}else{w.addEventListener('load',function(){k.focus()},true)};w.onunload=function(){}</script></html><!--ae75535d4a224623-->
非阻塞要不断的轮询, 浪费了CPU时间, 但是说与使用select机制相比, 到底那个机制更快,
也需要看情况, 我会继续试验.
对于read的结束条件, 具体看通信的协议.
http协议主要是看Content-Length, 还有一种是Transfer-Encoding: chunked,
我这个小demo实现的是根据Content-Length判断read结束.
over, 未完待续...
来源:http://hi.baidu.com/teng0210/blog/item/4955e8946e992b47d0135e2a.html
C语言HTTP请求GET,因对《所谓黑客揭秘》,大家都攻击代码的要求。所以我开始了为期两周的C/C++学习。由于没有任何C/C++基础,而是临时突击,所以代码肯定漏洞甚多,请观者见谅。同时欢迎拍砖或者支出代码错误,以求大家共同进步。:
来自:http://blog.csdn.net/aofengdaxia/article/details/5984431
静态库其实就是一堆.o文件的集合.
下面引用一个例子来说说静态库的创建与使用
//1.c中有一个简单的输出函数 func1
#include <stdio.h>
void func1()
{
printf("call func1\n");
}
//2.c中也有一个简单的输出函数 func2
#include <stdio.h>
void func2()
{
printf("call func2\n");
}
gcc生成目标文件
gcc -c 1.c 2.c
这样会生成1.o 2.o
接下来 我们创建静态库
使用ar命令
ar rv libmytest.a 1.o 2.o
这样就生成了静态库libmytest.a
使用静态库
//test.c
int main()
{
func1();
func2();
return 0;
}
编译
gcc -o test test.c libmytest.a
这样就生成了可执行文件
./test
call func1
call func2
PS:说说ar的简单使用
ar r test.a 1.o 2.o r选项是插入 将1.o, 2.o插入到test.a中 加上v 会打印提示
ar d test.a 1.o d选项是删除 将1.o从test.a中删除
ar t test.a t选项是列出详细信息 打印出test.a中的包含的文件
ar x test.a x选项是解压 解压出test.a中的文件
来源:http://hi.baidu.com/teng0210/blog/item/8df32a7ae666e3f90ad18780.html
上面的创建是没有问题的,但是你发现没有,1.c 2.c里面都有#include "stdio.h",而这时候对大规模开发程序是没有得到重复用的,
把它放到一个文件里,于是头文件出现了.h文件:
如下目录结构:
include/ lib/ libprint.a main* main.cpp Makefile print.cpp run.sh
print.cpp:注意没有包含 stdio.h
vi include/print.h :包含了stdio.h
vi main.cpp 这儿得包含了print.h了。
编译如下:
把上面的print.cpp 里面的#include "print.h"修改为:#include <stdio.h>,去掉main.cpp里面的#include "print.h",后按照上面开头那样用g++编译,会在最后报错:
所以,建议还是加上.h头文件为好!
g++ -c print.cpp -o lib/print.o
cd lib/
ar q libprint.a print.o
cd ..
g++ main.cpp ./lib/libprint.a
main.cpp: In function ¡®int main()¡¯:
main.cpp:5: error: ¡®printhello¡¯ was not declared in this s sco
全变为:.c后用:
gcc -c print.c -o lib/print.o
cd lib/
ar q libprint.a print.o
cd ..
gcc main.c ./lib/libprint.a
Ok了:
下面引用一个例子来说说静态库的创建与使用
//1.c中有一个简单的输出函数 func1
#include <stdio.h>
void func1()
{
printf("call func1\n");
}
//2.c中也有一个简单的输出函数 func2
#include <stdio.h>
void func2()
{
printf("call func2\n");
}
gcc生成目标文件
gcc -c 1.c 2.c
这样会生成1.o 2.o
接下来 我们创建静态库
使用ar命令
ar rv libmytest.a 1.o 2.o
这样就生成了静态库libmytest.a
使用静态库
//test.c
int main()
{
func1();
func2();
return 0;
}
编译
gcc -o test test.c libmytest.a
这样就生成了可执行文件
./test
call func1
call func2
PS:说说ar的简单使用
ar r test.a 1.o 2.o r选项是插入 将1.o, 2.o插入到test.a中 加上v 会打印提示
ar d test.a 1.o d选项是删除 将1.o从test.a中删除
ar t test.a t选项是列出详细信息 打印出test.a中的包含的文件
ar x test.a x选项是解压 解压出test.a中的文件
来源:http://hi.baidu.com/teng0210/blog/item/8df32a7ae666e3f90ad18780.html
上面的创建是没有问题的,但是你发现没有,1.c 2.c里面都有#include "stdio.h",而这时候对大规模开发程序是没有得到重复用的,
把它放到一个文件里,于是头文件出现了.h文件:
如下目录结构:
include/ lib/ libprint.a main* main.cpp Makefile print.cpp run.sh
print.cpp:注意没有包含 stdio.h
#include "print.h"
void printhello(){
printf("Hello, world\n");
}
void printhello(){
printf("Hello, world\n");
}
vi include/print.h :包含了stdio.h
#include <stdio.h>
//#include <cstdio>
void printhello();
//#include <cstdio>
void printhello();
vi main.cpp 这儿得包含了print.h了。
#include "print.h"
using namespace std;
int main(void)
{
printhello();
return 0;
}
using namespace std;
int main(void)
{
printhello();
return 0;
}
编译如下:
g++ -o ./lib/print.o -c print.cpp -I/root/c++/include
ar q ./lib/libprint.a ./lib/print.o
g++ main.cpp -o main -I/root/c++/include -L/root/c++/lib -lprint
ar q ./lib/libprint.a ./lib/print.o
g++ main.cpp -o main -I/root/c++/include -L/root/c++/lib -lprint
./main
Hello, world
Hello, world
把上面的print.cpp 里面的#include "print.h"修改为:#include <stdio.h>,去掉main.cpp里面的#include "print.h",后按照上面开头那样用g++编译,会在最后报错:
# gcc main.cpp ./lib/print.o
main.cpp: In function ¡®int main()¡¯:
main.cpp:5: error: ¡®printhello¡¯ was not declared in this scop
main.cpp: In function ¡®int main()¡¯:
main.cpp:5: error: ¡®printhello¡¯ was not declared in this scop
所以,建议还是加上.h头文件为好!
g++ -c print.cpp -o lib/print.o
cd lib/
ar q libprint.a print.o
cd ..
g++ main.cpp ./lib/libprint.a
main.cpp: In function ¡®int main()¡¯:
main.cpp:5: error: ¡®printhello¡¯ was not declared in this s sco
全变为:.c后用:
gcc -c print.c -o lib/print.o
cd lib/
ar q libprint.a print.o
cd ..
gcc main.c ./lib/libprint.a
Ok了:
./main
Hello, world
Hello, world
PHP中有一种数据类型非常重要,它就是关联数组,又称为哈希表(hash table),是一种非常好用的数据结构。
在程序中,我们可能会遇到需要消重的问题,举一个最简单的模型:
有一份用户名列表,存储了 10000 个用户名,没有重复项;
还有一份黑名单列表,存储了 2000 个用户名,格式与用户名列表相同;
现在需要从用户名列表中删除处在黑名单里的用户名,要求用尽量快的时间处理。
这个问题是一个小规模的处理量,如果实际一点,2 个表都可能很大,比如有 2 亿条记录。
我最开始想到的方法,就是做一个嵌套的循环,设用户名表有 M 条记录,黑名单列表有 N 条记录,那么,循环的次数是 M * N 次!
PHP 版代码:
另一种方式,利用数组索引。
PHP 是一种弱类型的语言,不像 C 语言那样有严格的变量类型限制。C 语言的数组,每一个元素的类型必须一致,而且索引都是从 0 开始。
PHP 的数组,可以用字符串作为索引,也称为关联数组。
数组索引,有一个天然的限制就是不会重复,而且访问的时候不需要查找,可以直接定位。
还是刚才的那个问题,我们采用另一种办法。
把黑名单列表的用户名组织到一个数组里,数组的索引就是用户名。
然后,遍历用户列表的时候,只需直接用 isset 查询那个用户名是否存在即可。
PHP 版代码:
可以看到,优化过的代码,循环次数是 M + N 次。
假如 M 和 N 都是 10000,优化前,循环了 1 亿次;优化后,只循环了 20000 次,差了 5000 倍!
如果第二个程序耗时 1 秒,则第一个程序需要将近一个半小时!
=========================================================================
hash一个貌似比较复杂的东西,实际上理解起来并不那么夸张,这里做个笔记。
hash,中文翻译成杂乱的东西,有人也叫它杂凑,或者翻译成什么都不是的音译“哈希”。
简单说来,hash就是为了把一个复杂的字串,通过一定的转换,得到一个简单的数字(通常是数字)。
如"abcd" 用各个字符的值直接相加,再取对10的余数,既(a+b+c+d)%10,来得到一个数字,比方说结果为5,那么这个5就能在一定意义上代表这个字串 abcd了。或者说这个5也可以说是这个字串的一个标记性的东西,而且是简化了的标记,所以又有人叫这个5为字串的摘要,或指纹。
这个5,有一个好的用处就是可以作为一个数组的下标来用,如我自己构造一个指针数组void* hash_array[10],那么我就可以把5那个位置上填上一个指针,如指向abcd字串。
这样的话,我如果要去查询一个字串是否存在,就不需要对一个数组使用字符串循环对比这样的慢操作,而直接先得到某个字串的hash值,再用这个hash值,在数组下标里直接找,这样速度要快上很多,特别是数据比较多的时候。
可以看到上面计算hash值时,出来的结果,可能并不是从0开始的,如我们算出的就是5。也就是说,这个5是在数组中的某个不确定的位置,或者可以叫做是一个杂凑出来的位置。其他位置可能一直就空着在。这就是这个数组或表格叫hash表的原因了。
但有个问题,上面的转换方法,直接相加,再取个余数,在字符串变为abdc时,结果得到的还是数字5。这个就是上面这个算法的一个问题了,即它不能保证一个唯一性。所以就出现了很多hash算法的研究,如MD4,MD5,SHA-1等,来保证唯一性。
但上面这个算法还是可以使用的,做法就是在abdc经过hash得到5后,去检查5是否被占用,如果占用了,那么就把数字加1,即为6,如果6没被占用,就填上值。如果后面某个字串算出一个值是6,但6已经被占用了,那么就再加1,再存。
取数据的时候,可以先算出hash值后,再看里面的内容是不是你想要的,如果不是,就加1去看,最后得到一个。
所以这里hash表的内容并不是象一般的数组最开始就组织好了的,而是后续慢慢往里增加的。
hash表里存的内容一般可以是一个指针,这个指针可以指向一个大的结构也是可以的。这个结构里可以有key, value信息。
hash表也可以不是数组,你可以把它组织成一个链表,链表里的node的结构中可以有一个参数就是那个数字的hash_value,用来快速查找用。
虽然在很多时候hash被用在加密等场合,但在一般的应用程序代码中,也可以用它来存贮简单的数据,这样代码的效率会高很多。
转载:http://hi.baidu.com/kuien_jiang/blog/item/4dbe2adcf9d9bba6cc116600.html
在程序中,我们可能会遇到需要消重的问题,举一个最简单的模型:
有一份用户名列表,存储了 10000 个用户名,没有重复项;
还有一份黑名单列表,存储了 2000 个用户名,格式与用户名列表相同;
现在需要从用户名列表中删除处在黑名单里的用户名,要求用尽量快的时间处理。
这个问题是一个小规模的处理量,如果实际一点,2 个表都可能很大,比如有 2 亿条记录。
我最开始想到的方法,就是做一个嵌套的循环,设用户名表有 M 条记录,黑名单列表有 N 条记录,那么,循环的次数是 M * N 次!
PHP 版代码:
01 <?php
02 foreach($arrayM as $keyM => $nameM) {
03 foreach($arrayN as $nameN) {
04 if ($nameM == $nameN) {
05 // 本行执行了 M * N 次!
06 unset($arrayM[$keyM]);
07 }
08 }
09 }
10 return $arrayM;
11 ?>
02 foreach($arrayM as $keyM => $nameM) {
03 foreach($arrayN as $nameN) {
04 if ($nameM == $nameN) {
05 // 本行执行了 M * N 次!
06 unset($arrayM[$keyM]);
07 }
08 }
09 }
10 return $arrayM;
11 ?>
另一种方式,利用数组索引。
PHP 是一种弱类型的语言,不像 C 语言那样有严格的变量类型限制。C 语言的数组,每一个元素的类型必须一致,而且索引都是从 0 开始。
PHP 的数组,可以用字符串作为索引,也称为关联数组。
数组索引,有一个天然的限制就是不会重复,而且访问的时候不需要查找,可以直接定位。
还是刚才的那个问题,我们采用另一种办法。
把黑名单列表的用户名组织到一个数组里,数组的索引就是用户名。
然后,遍历用户列表的时候,只需直接用 isset 查询那个用户名是否存在即可。
PHP 版代码:
01 <?php
02 $arrayHash = array();
03 foreach($arrayN as $nameN) {
04 // 本行执行了 N 次。
05 $arrayHash[$nameN] = 1;
06 }
07
08 foreach($arrayM as $keyM => $nameM) {
09 if (isset($arrayHash[$nameM])) {
10 // 本行执行了 M 次!
11 unset($arrayM[$keyM]);
12 }
13 }
14 return $arrayM;
15 ?>
02 $arrayHash = array();
03 foreach($arrayN as $nameN) {
04 // 本行执行了 N 次。
05 $arrayHash[$nameN] = 1;
06 }
07
08 foreach($arrayM as $keyM => $nameM) {
09 if (isset($arrayHash[$nameM])) {
10 // 本行执行了 M 次!
11 unset($arrayM[$keyM]);
12 }
13 }
14 return $arrayM;
15 ?>
可以看到,优化过的代码,循环次数是 M + N 次。
假如 M 和 N 都是 10000,优化前,循环了 1 亿次;优化后,只循环了 20000 次,差了 5000 倍!
如果第二个程序耗时 1 秒,则第一个程序需要将近一个半小时!
=========================================================================
hash一个貌似比较复杂的东西,实际上理解起来并不那么夸张,这里做个笔记。
hash,中文翻译成杂乱的东西,有人也叫它杂凑,或者翻译成什么都不是的音译“哈希”。
简单说来,hash就是为了把一个复杂的字串,通过一定的转换,得到一个简单的数字(通常是数字)。
如"abcd" 用各个字符的值直接相加,再取对10的余数,既(a+b+c+d)%10,来得到一个数字,比方说结果为5,那么这个5就能在一定意义上代表这个字串 abcd了。或者说这个5也可以说是这个字串的一个标记性的东西,而且是简化了的标记,所以又有人叫这个5为字串的摘要,或指纹。
这个5,有一个好的用处就是可以作为一个数组的下标来用,如我自己构造一个指针数组void* hash_array[10],那么我就可以把5那个位置上填上一个指针,如指向abcd字串。
这样的话,我如果要去查询一个字串是否存在,就不需要对一个数组使用字符串循环对比这样的慢操作,而直接先得到某个字串的hash值,再用这个hash值,在数组下标里直接找,这样速度要快上很多,特别是数据比较多的时候。
可以看到上面计算hash值时,出来的结果,可能并不是从0开始的,如我们算出的就是5。也就是说,这个5是在数组中的某个不确定的位置,或者可以叫做是一个杂凑出来的位置。其他位置可能一直就空着在。这就是这个数组或表格叫hash表的原因了。
但有个问题,上面的转换方法,直接相加,再取个余数,在字符串变为abdc时,结果得到的还是数字5。这个就是上面这个算法的一个问题了,即它不能保证一个唯一性。所以就出现了很多hash算法的研究,如MD4,MD5,SHA-1等,来保证唯一性。
但上面这个算法还是可以使用的,做法就是在abdc经过hash得到5后,去检查5是否被占用,如果占用了,那么就把数字加1,即为6,如果6没被占用,就填上值。如果后面某个字串算出一个值是6,但6已经被占用了,那么就再加1,再存。
取数据的时候,可以先算出hash值后,再看里面的内容是不是你想要的,如果不是,就加1去看,最后得到一个。
所以这里hash表的内容并不是象一般的数组最开始就组织好了的,而是后续慢慢往里增加的。
hash表里存的内容一般可以是一个指针,这个指针可以指向一个大的结构也是可以的。这个结构里可以有key, value信息。
hash表也可以不是数组,你可以把它组织成一个链表,链表里的node的结构中可以有一个参数就是那个数字的hash_value,用来快速查找用。
虽然在很多时候hash被用在加密等场合,但在一般的应用程序代码中,也可以用它来存贮简单的数据,这样代码的效率会高很多。
转载:http://hi.baidu.com/kuien_jiang/blog/item/4dbe2adcf9d9bba6cc116600.html
Loadrunner对Linux的监控点不是很多,分析起来很费力,看到不少人都提到了nmon就试用了一下,感觉还不错,就是有个缺点,与Loadrunner的场景执行时间有个时间差的问题,但是个人认为最终数据虽然会有些偏差,但是不影响性能分析,这个因素可以忽略掉
nmon用起来很简单,无需安装,解压后直接就可以使用了
一、下载
nmon下载地址:http://www-941.haw.ibm.com/collaboration/wiki/display/WikiPtype/nmon
nmon还带了个分析工具,下载地址:http://www-941.haw.ibm.com/collaboration/wiki/display/Wikiptype/nmonanalyser
二、安装
下载完成后,把压缩包解压,上传到服务器的任意目录,如/usr/local/nmon
我的服务器是Redhat server 5.3的,发现虽然没有对应的5.3的版本,下载5.2的也可以使用
三、启动
打开nmon所在的目录:cd /usr/local/nmon
修改启动文件的访问权限:chmod 755 nmon_x86_rhel52
启动nmon:./nmon_x86_rhel52
如果要采样nmon的数据保存成文件,可以
./nmon_x86_rhel52 -fT -s 30 -c 120
其中30表示每隔30秒nmon取一次系统性能数据,120表示取120次;
这样nmon将会在运行开始算起连续取得30sX120=60分钟,可根据实际需要时间调整;当运行以上命令后该目录下会生成一个.nmon文件,该文件会根据间隔时间被写入性能数据,当一段时间后再查看该文件,文件字节变大
利用nmonanalyser分析.nmon文件
当测试结束的同时ftp到服务器上将.nmon文件get下来,
打开nmon_analyser.zip 包下的nmon analyser v338.xls 文件,点击Analyse nomn data按钮,选择之前get来下的.nmon文件。
(如果报告以下宏的安全级别太高错误,则在“工具 -- 宏 --安全性”里把级别调低,然后重新打开 nmon analyser v338.xls 文件)
待分析结束后会生成性能分析结果文件(文件格式为.xls,其中包括CPU,IO,内存等性能分析报告)。
分析结果中有很多数据和图形,简要介绍主要的性能参数图像
4.1 系统汇总(对应excel标签的‘SYS_SUMM’)
蓝线为cpu占有率变化情况;
粉线为磁盘IO的变化情况;
4.2磁盘读写情况汇总(对应excel标签的‘DISK_SUMM’)
蓝色为磁盘读的速率KB/sec
紫色为磁盘写的速率KB/sec
4.3内存情况汇总(对应excel标签的‘MEM’)
曲线表示内存剩余量(MB)
分析数据得到的报告文件(.xls)中包含很多性能分析结果数据,根据自己的需要查看。
五、nmon运行本身就消耗系统资源的;
另外如果取到.nmon文件后确定不再需要nmon继续收集信息则应kill掉nmon;
命令:
ps -A | grep nmon #得到pid
kill -9 pid
suse10 enterprise sp2:
nmon_x86_rhel3
使用对应的操作系统文件:
chmod +x nmon_x86_ubuntu810
mv nmon_x86_ubuntu810 /usr/local/bin/nmon
对于 Debian 还要做以下操作(不做也同样能运行):
apt-get install lsb-release
lsb_release -d | sed 's/Description:\t//' > /etc/debian_release
然后直接运行 nmon 即可。
采集数据并生成报表:
采集数据:
nmon -s10 -c60 -f -m /home/
参数解释:
-s10 每 10 秒采集一次数据。
-c60 采集 60 次,即为采集十分钟的数据。
-f 生成的数据文件名中包含文件创建的时间。
-m 生成的数据文件的存放目录。
这样就会生成一个 nmon 文件,并每十秒更新一次,直到十分钟后。
生成的文件名如: hostname_090824_1306.nmon ,"hostname" 是这台主机的主机名。
生成报表:
下载 nmon analyser (生成性能报告的免费工具):
http://www.ibm.com/developerworks/wikis/display/Wikiptype/nmonanalyser
把之前生成的 nmon 数据文件传到 Windows 机器上,用 Excel 打开分析工具 nmon analyser v33C.xls 。点击 Excel 文件中的 "Analyze nmon data" 按钮,选择 nmon 数据文件,这样就会生成一个分析后的结果文件: hostname_090824_1306.nmon.xls ,用 Excel 打开生成的文件就可以看到结果了。
如果宏不能运行,需要做以下操作:
工具 -> 宏 -> 安全性 -> 中,然后再打开文件并允许运行宏。
自动按天采集数据:
在 crontab 中增加一条记录:
0 0 * * * root nmon -s300 -c288 -f -m /home/ > /dev/null 2>&1
300*288=86400 秒,正好是一天的数据。
采样文件越来越大:
jackxiang@172.25.39.***:~/nmon# ./nmon -s1 -c33 -f
jackxiang@172.25.39.***:~/nmon#
jackxiang@172.25.39.***:~/nmon# du -sh *
8.0K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
12K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
16K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
20K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
20K AD39_***_sles10_101207_1046.nmon
160K nmon
nmon用起来很简单,无需安装,解压后直接就可以使用了
一、下载
nmon下载地址:http://www-941.haw.ibm.com/collaboration/wiki/display/WikiPtype/nmon
nmon还带了个分析工具,下载地址:http://www-941.haw.ibm.com/collaboration/wiki/display/Wikiptype/nmonanalyser
二、安装
下载完成后,把压缩包解压,上传到服务器的任意目录,如/usr/local/nmon
我的服务器是Redhat server 5.3的,发现虽然没有对应的5.3的版本,下载5.2的也可以使用
三、启动
打开nmon所在的目录:cd /usr/local/nmon
修改启动文件的访问权限:chmod 755 nmon_x86_rhel52
启动nmon:./nmon_x86_rhel52
如果要采样nmon的数据保存成文件,可以
./nmon_x86_rhel52 -fT -s 30 -c 120
其中30表示每隔30秒nmon取一次系统性能数据,120表示取120次;
这样nmon将会在运行开始算起连续取得30sX120=60分钟,可根据实际需要时间调整;当运行以上命令后该目录下会生成一个.nmon文件,该文件会根据间隔时间被写入性能数据,当一段时间后再查看该文件,文件字节变大
利用nmonanalyser分析.nmon文件
当测试结束的同时ftp到服务器上将.nmon文件get下来,
打开nmon_analyser.zip 包下的nmon analyser v338.xls 文件,点击Analyse nomn data按钮,选择之前get来下的.nmon文件。
(如果报告以下宏的安全级别太高错误,则在“工具 -- 宏 --安全性”里把级别调低,然后重新打开 nmon analyser v338.xls 文件)
待分析结束后会生成性能分析结果文件(文件格式为.xls,其中包括CPU,IO,内存等性能分析报告)。
分析结果中有很多数据和图形,简要介绍主要的性能参数图像
4.1 系统汇总(对应excel标签的‘SYS_SUMM’)
蓝线为cpu占有率变化情况;
粉线为磁盘IO的变化情况;
4.2磁盘读写情况汇总(对应excel标签的‘DISK_SUMM’)
蓝色为磁盘读的速率KB/sec
紫色为磁盘写的速率KB/sec
4.3内存情况汇总(对应excel标签的‘MEM’)
曲线表示内存剩余量(MB)
分析数据得到的报告文件(.xls)中包含很多性能分析结果数据,根据自己的需要查看。
五、nmon运行本身就消耗系统资源的;
另外如果取到.nmon文件后确定不再需要nmon继续收集信息则应kill掉nmon;
命令:
ps -A | grep nmon #得到pid
kill -9 pid
suse10 enterprise sp2:
nmon_x86_rhel3
使用对应的操作系统文件:
chmod +x nmon_x86_ubuntu810
mv nmon_x86_ubuntu810 /usr/local/bin/nmon
对于 Debian 还要做以下操作(不做也同样能运行):
apt-get install lsb-release
lsb_release -d | sed 's/Description:\t//' > /etc/debian_release
然后直接运行 nmon 即可。
采集数据并生成报表:
采集数据:
nmon -s10 -c60 -f -m /home/
参数解释:
-s10 每 10 秒采集一次数据。
-c60 采集 60 次,即为采集十分钟的数据。
-f 生成的数据文件名中包含文件创建的时间。
-m 生成的数据文件的存放目录。
这样就会生成一个 nmon 文件,并每十秒更新一次,直到十分钟后。
生成的文件名如: hostname_090824_1306.nmon ,"hostname" 是这台主机的主机名。
生成报表:
下载 nmon analyser (生成性能报告的免费工具):
http://www.ibm.com/developerworks/wikis/display/Wikiptype/nmonanalyser
把之前生成的 nmon 数据文件传到 Windows 机器上,用 Excel 打开分析工具 nmon analyser v33C.xls 。点击 Excel 文件中的 "Analyze nmon data" 按钮,选择 nmon 数据文件,这样就会生成一个分析后的结果文件: hostname_090824_1306.nmon.xls ,用 Excel 打开生成的文件就可以看到结果了。
如果宏不能运行,需要做以下操作:
工具 -> 宏 -> 安全性 -> 中,然后再打开文件并允许运行宏。
自动按天采集数据:
在 crontab 中增加一条记录:
0 0 * * * root nmon -s300 -c288 -f -m /home/ > /dev/null 2>&1
300*288=86400 秒,正好是一天的数据。
采样文件越来越大:
jackxiang@172.25.39.***:~/nmon# ./nmon -s1 -c33 -f
jackxiang@172.25.39.***:~/nmon#
jackxiang@172.25.39.***:~/nmon# du -sh *
8.0K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
12K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
16K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
20K AD39_***_sles10_101207_1046.nmon
160K nmon
jackxiang@172.25.39.***:~/nmon# du -sh *
20K AD39_***_sles10_101207_1046.nmon
160K nmon
什么是库
库文件是一些预先编译好的函数的集合,那些函数都是按照可再使用的原则编写的。它们通常由一组互相关联的用来完成某项常见工作的函数构成,从本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
无论在Windows平台还是在Linux平台下都存在大量的库,但由于Windows和Linux的本质不同,因此二者的库的二进制是不兼容的。
库的分类
Windows下的库有两种:静态库(.lib)和动态链接库(.dll)。
Linux下的库有两种:静态库(.a)和共享库(.so)。
Linux下的静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
Linux下的动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号,minor是副版本号。
Windows下的库与Linux下的库的异同
Linux的共享库(.so)就象Windows的动态链接库(.dll),它里面包含有很多程序常用的函数。为了方便程序开发和减少程序的冗余,程序当中就不用包含每个常用函数的拷贝,只是在需要时调用共享库中常函数即可。这种方式我们称之为动态链接(Dynamically Linked)。而有时我们不希望叫程序去调用共享库的函数,而是把库函数代码直接链接进程序代码中,也就是说,在程序本身拥有一份共享库中函数的副本。这种方式我们称之为静态链接(Statically Linked)。
所以,简单的讲静态库和共享库(动态库)的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
Windows下的动态链接库(.dll)与Linux下的共享库(.so)的差别
.dll文件事实上和.exe文件一样,同属 PE 格式的执行文件。对于隐式的引用外部符号,需要把外部符号所在的位置写在PE头上。PE加载器将从PE头上找到依赖的符号表,并加载依赖的其它.dll文件。
而在Linux 上并非如此!.so文件大多为elf执行文件格式。当它们需要的外部符号,可以不写明这些符号所在的位置。也就是说,通常.so文件本身并不知道它依赖的那些符号在哪些.so里面。这些符号是由调用dlopen的进程运行时提供的。
我们在Windows下做一个.dll文件时还需要携带一个.lib文件;而在Linux下一般只需要有相应的头文件就够了。对于编写新的.so,找不到的符号可以就让它在那里,直到最终执行文件来把所有需要的符号联合到一起。windows 可以存在一个.dll对另一个.dll的隐式依赖;而Linux下一般不需要让.so和.so有隐式依赖关系。
库文件是一些预先编译好的函数的集合,那些函数都是按照可再使用的原则编写的。它们通常由一组互相关联的用来完成某项常见工作的函数构成,从本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
无论在Windows平台还是在Linux平台下都存在大量的库,但由于Windows和Linux的本质不同,因此二者的库的二进制是不兼容的。
库的分类
Windows下的库有两种:静态库(.lib)和动态链接库(.dll)。
Linux下的库有两种:静态库(.a)和共享库(.so)。
Linux下的静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
Linux下的动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号,minor是副版本号。
Windows下的库与Linux下的库的异同
Linux的共享库(.so)就象Windows的动态链接库(.dll),它里面包含有很多程序常用的函数。为了方便程序开发和减少程序的冗余,程序当中就不用包含每个常用函数的拷贝,只是在需要时调用共享库中常函数即可。这种方式我们称之为动态链接(Dynamically Linked)。而有时我们不希望叫程序去调用共享库的函数,而是把库函数代码直接链接进程序代码中,也就是说,在程序本身拥有一份共享库中函数的副本。这种方式我们称之为静态链接(Statically Linked)。
所以,简单的讲静态库和共享库(动态库)的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
Windows下的动态链接库(.dll)与Linux下的共享库(.so)的差别
.dll文件事实上和.exe文件一样,同属 PE 格式的执行文件。对于隐式的引用外部符号,需要把外部符号所在的位置写在PE头上。PE加载器将从PE头上找到依赖的符号表,并加载依赖的其它.dll文件。
而在Linux 上并非如此!.so文件大多为elf执行文件格式。当它们需要的外部符号,可以不写明这些符号所在的位置。也就是说,通常.so文件本身并不知道它依赖的那些符号在哪些.so里面。这些符号是由调用dlopen的进程运行时提供的。
我们在Windows下做一个.dll文件时还需要携带一个.lib文件;而在Linux下一般只需要有相应的头文件就够了。对于编写新的.so,找不到的符号可以就让它在那里,直到最终执行文件来把所有需要的符号联合到一起。windows 可以存在一个.dll对另一个.dll的隐式依赖;而Linux下一般不需要让.so和.so有隐式依赖关系。
丹麦哲学家布里丹曾写过一则寓言:有头毛驴,在干枯的草原上极为幸运地找到两堆
草,由于不知道先吃哪一堆好,结果在无限的选择和徘徊中饿死了。这被称为“布里丹效
应”。
这个寓言多年来一直是针对人类的选择而言的,即面对多种选择,人们往往无从选择。
但我现在看它,心境已完全不一样,社会发展到现在,物质生活极为丰富,人的自由度也
大了许多,已经到了可以有更多选择,追求更多选择的时代。以上面的寓言为例,在仅有
的两堆草里选,而且是在此后也不知道哪里还有草的情况下,这不叫选择,更不是我们现
在所说的更多选择。反而更像标准之选,是只能二取一的抉择,非左即右,非生即死。
什么是更多选择呢,我认为应该像大型超市,即使是最普通的商品,超市也会摆满货
架,琳琅满目,比如牛奶,有众多品牌、众多类型的口味和包装,每个人都可以根据自己
的偏好进行选择。但这种选择是建立在统一的牛奶标准之上的,因为标准统一,我们需要
考虑的只是自己的偏好,也可以在众多选择中放任自己的偏好,还可以随时改变自己的偏
好,正是在这种种偏好的满足下,我们才成就了“我们决定自己的口袋,我们决定我们的
购物篮”的“上帝”之感。假设牛奶的标准不一致,我们才真会感到无所适从。可以说,
多个标准往往会让我们无从选择,反而限制了我们选择的自由。我曾举过手机充电器的例
子,每个厂家都有自己的充电器标准,甚至每个型号都有自己的充电器标准,我们又何曾
多了更多选择。
多标准不仅会限制我们的选择,在很多时候,还可能造成极大的危害。因为多标准而
造成的教训有很多,比如:
1904 年的巴尔的摩火灾,因每个城市的水管标准都不同,所以从别的城市赶来救援的
消防队员只能望“火”兴叹,最终 80 个街区被烧为平地。
同样在美国,据说铁路规格不同是美国南部输掉美国南北战争的重要原因之一。
近期的教训也有,因为测量单位英式与公制的区别,美国航空局曾丢失了一个价值 1.25
亿美元的火星轨道飞行器。
在我国,以办公软件为例,多年来,封闭文档格式的存在严重阻碍了各中文办公软件
之间的文档互通,用户几乎是别无选择地被长期锁定在某一软件上。这不仅不利于国产软
件的发展,对于用户本身来说,长期被锁定一家软件会对文档的长期保存带来极大隐患。
正因为如此,制定统一的中文文档格式国家标准 UOF 成为我们共同的诉求。
我一直坚持这样的观点,更多的选择应建立在统一的开放的标准基础之上。
在这里,我想到近期的一个新闻热点——蓝光 DVD 和 HDDVD 的对垒。这两种格式
的 DVD 厚度不同,互不兼容,统一的标准一直难以出现,市场和用户都出现观望态势,
两者的推广之路都受到标准不统一的阻碍。目前,这种状况有了突破,华纳兄弟宣布放弃
HDDVD转而支持蓝光 DVD,使蓝光阵营进一步壮大,舆论一致认为 HDDVD格式处于劣
势,占据上风的蓝光有望成为新一代 DVD 标准。但也有意见指出,电子市场变化迅猛,
如果标准的市场化不紧跟上,即使成为统一标准,也面临严峻挑战。多年受困于标准之乱
的 DVD行业,可能已经错过了他们最好的发展时期,借标准一统天下的目标或许能实现,
但天下已经不是从前的天下了,近几年崛起的视频网络的发展已经改变众多消费者的观影
习惯,对于 DVD的发展可以说是雪上加霜。
与 DVD 标准情况相似,标准推广和市场化的时机极为重要。UOF 出台后,惟有真正
应用起来,推广开去,才能发挥其作用。目前正值微软技术转型,用户的使用习惯经历巨
变,需要重新建立,这将为国产软件的发展创造良好的机遇。可以说,这一机遇的把握与
否将直接关乎国产软件乃至我国信息产业的发展成败
草,由于不知道先吃哪一堆好,结果在无限的选择和徘徊中饿死了。这被称为“布里丹效
应”。
这个寓言多年来一直是针对人类的选择而言的,即面对多种选择,人们往往无从选择。
但我现在看它,心境已完全不一样,社会发展到现在,物质生活极为丰富,人的自由度也
大了许多,已经到了可以有更多选择,追求更多选择的时代。以上面的寓言为例,在仅有
的两堆草里选,而且是在此后也不知道哪里还有草的情况下,这不叫选择,更不是我们现
在所说的更多选择。反而更像标准之选,是只能二取一的抉择,非左即右,非生即死。
什么是更多选择呢,我认为应该像大型超市,即使是最普通的商品,超市也会摆满货
架,琳琅满目,比如牛奶,有众多品牌、众多类型的口味和包装,每个人都可以根据自己
的偏好进行选择。但这种选择是建立在统一的牛奶标准之上的,因为标准统一,我们需要
考虑的只是自己的偏好,也可以在众多选择中放任自己的偏好,还可以随时改变自己的偏
好,正是在这种种偏好的满足下,我们才成就了“我们决定自己的口袋,我们决定我们的
购物篮”的“上帝”之感。假设牛奶的标准不一致,我们才真会感到无所适从。可以说,
多个标准往往会让我们无从选择,反而限制了我们选择的自由。我曾举过手机充电器的例
子,每个厂家都有自己的充电器标准,甚至每个型号都有自己的充电器标准,我们又何曾
多了更多选择。
多标准不仅会限制我们的选择,在很多时候,还可能造成极大的危害。因为多标准而
造成的教训有很多,比如:
1904 年的巴尔的摩火灾,因每个城市的水管标准都不同,所以从别的城市赶来救援的
消防队员只能望“火”兴叹,最终 80 个街区被烧为平地。
同样在美国,据说铁路规格不同是美国南部输掉美国南北战争的重要原因之一。
近期的教训也有,因为测量单位英式与公制的区别,美国航空局曾丢失了一个价值 1.25
亿美元的火星轨道飞行器。
在我国,以办公软件为例,多年来,封闭文档格式的存在严重阻碍了各中文办公软件
之间的文档互通,用户几乎是别无选择地被长期锁定在某一软件上。这不仅不利于国产软
件的发展,对于用户本身来说,长期被锁定一家软件会对文档的长期保存带来极大隐患。
正因为如此,制定统一的中文文档格式国家标准 UOF 成为我们共同的诉求。
我一直坚持这样的观点,更多的选择应建立在统一的开放的标准基础之上。
在这里,我想到近期的一个新闻热点——蓝光 DVD 和 HDDVD 的对垒。这两种格式
的 DVD 厚度不同,互不兼容,统一的标准一直难以出现,市场和用户都出现观望态势,
两者的推广之路都受到标准不统一的阻碍。目前,这种状况有了突破,华纳兄弟宣布放弃
HDDVD转而支持蓝光 DVD,使蓝光阵营进一步壮大,舆论一致认为 HDDVD格式处于劣
势,占据上风的蓝光有望成为新一代 DVD 标准。但也有意见指出,电子市场变化迅猛,
如果标准的市场化不紧跟上,即使成为统一标准,也面临严峻挑战。多年受困于标准之乱
的 DVD行业,可能已经错过了他们最好的发展时期,借标准一统天下的目标或许能实现,
但天下已经不是从前的天下了,近几年崛起的视频网络的发展已经改变众多消费者的观影
习惯,对于 DVD的发展可以说是雪上加霜。
与 DVD 标准情况相似,标准推广和市场化的时机极为重要。UOF 出台后,惟有真正
应用起来,推广开去,才能发挥其作用。目前正值微软技术转型,用户的使用习惯经历巨
变,需要重新建立,这将为国产软件的发展创造良好的机遇。可以说,这一机遇的把握与
否将直接关乎国产软件乃至我国信息产业的发展成败
1.此刻打盹,你将做梦;而此刻学习,你将圆梦。
2.我荒废的今日,正是昨日殒身之人祈求的明日。
3.觉得为时已晚的时候,恰恰是最早的时候。
4.勿将今日之事拖到明日。
5.学习时的苦痛是暂时的,未学到的痛苦是终生的。
6.学习这件事,不是缺乏时间,而是缺乏努力。
7.幸福或许不排名次,但成功必排名次。
8.学习并不是人生的全部。但既然连人生的一部分——学习也无法征服,还能做什么呢?
9.请享受无法回避的痛苦。
10.只有比别人更早、更勤奋地努力,才能尝到成功的滋味。
11.谁也不能随随便便成功,它来自彻底的自我管理和毅力。
12.时间在流逝。
13.现在流的口水,将成为明天的眼泪。
14.狗一样地学,绅士一样地玩。
15.今天不走,明天要跑。
16.投资未来的人,是忠于现实的人。
17.受教育程度代表收入。
18.一天过完,不会再来。
19.即使现在,对手也不停地翻动书页。
20.没有艰辛,便无所获。
2.我荒废的今日,正是昨日殒身之人祈求的明日。
3.觉得为时已晚的时候,恰恰是最早的时候。
4.勿将今日之事拖到明日。
5.学习时的苦痛是暂时的,未学到的痛苦是终生的。
6.学习这件事,不是缺乏时间,而是缺乏努力。
7.幸福或许不排名次,但成功必排名次。
8.学习并不是人生的全部。但既然连人生的一部分——学习也无法征服,还能做什么呢?
9.请享受无法回避的痛苦。
10.只有比别人更早、更勤奋地努力,才能尝到成功的滋味。
11.谁也不能随随便便成功,它来自彻底的自我管理和毅力。
12.时间在流逝。
13.现在流的口水,将成为明天的眼泪。
14.狗一样地学,绅士一样地玩。
15.今天不走,明天要跑。
16.投资未来的人,是忠于现实的人。
17.受教育程度代表收入。
18.一天过完,不会再来。
19.即使现在,对手也不停地翻动书页。
20.没有艰辛,便无所获。
[1]好好规划自己的路,不要跟着感觉走!根据个人的理想决策安排,绝大部分人并不指望成为什么院士或教授,而是希望活得滋润一些,爽一些。那么,就需要慎重安排自己的轨迹。从哪个行业入手,逐渐对该行业深入了解,不要频繁跳槽,特别是不要为了一点工资而转移阵地,从长远看,这点钱根本不算什么,当你对一个行业有那么几年的体会,以后钱根本不是问题。频繁地动荡不是上策,最后你对哪个行业都没有摸透,永远是新手!
[2]可以做技术,切不可沉湎于技术。千万不可一门心思钻研技术!给自己很大压力,如果你的心思全部放在这上面,那么注定你将成为孔乙己一类的人物!适可而止,因为技术只不过是你今后前途的支柱之一,而且还不是最大的支柱,除非你只愿意到老还是个注册安全工程师!
[3]不要去做技术高手,只去做综合素质高手!在企业里混,我们时常瞧不起某人,说他“什么都不懂,凭啥拿那么多钱,凭啥升官!”这是普遍的典型的注册安全工程师的迂腐之言。某某人很牛吗?人家能上去必然有他的本事,而且是你没有的本事。你想想,老板搞经营那么多年,难道见识不如你这个新兵?人家或许善于管理,善于领会老板意图,善于部门协调等等。因此务必培养自己多方面的能力,包括管理,亲和力,察言观色能力,攻关能力等,要成为综合素质的高手,则前途无量,否则只能躲在角落看显示器!技术以外的技能才是更重要的本事!!从古到今,美国、日本,一律如此!
[4]多交社会三教九流的朋友!不要只和注册安全工程师交往,认为有共同语言,其实更重要的是和其他类人物交往,如果你希望有朝一日当老板或高层管理,那么你整日面对的就是这些人。了解他们的经历,思维习惯,爱好,学习他们处理问题的模式,了解社会各个角落的现象和问题,这是以后发展的巨大的本钱,没有这些以后就会笨手笨脚,跌跌撞撞,遇到重重困难,交不少学费,成功的概率大大降低!
[5]知识涉猎不一定专,但一定要广!多看看其他方面的书,金融,财会,进出口,税务,法律等等,为以后做一些积累,以后的用处会更大!会少交许多学费!
[6]抓住时机向技术管理或市场销售方面的转变!要想有前途就不能一直搞技术,适当时候要转变为管理或销售,前途会更大,以前搞技术也没有白搞,以后还用得着。搞管理可以培养自己的领导能力,搞销售可以培养自己的市场概念和思维,同时为自己以后发展积累庞大的人脉!应该说这才是前途的真正支柱!!!
[7]逐渐克服自己的心里弱点和性格缺陷!多疑,敏感,天真(贬义,并不可爱),犹豫不决,胆怯,多虑,脸皮太薄,心不够黑,教条式思维。。。这些注册安全工程师普遍存在的性格弱点必须改变!很难吗?只在床上想一想当然不可能,去帮朋友守一个月地摊,包准有效果,去实践,而不要只想!不克服这些缺点,一切不可能,甚至连项目经理都当不好--尽管你可能技术不错!
[8]工作的同时要为以后做准备!建立自己的工作环境!及早为自己配置一个工作环境,一方面接触市场,培养市场感觉,同时也积累资金,更重要的是准备自己的产品,咱搞技术的没有钱,只有技术,技术的代表不是学历和证书,而是产品,拿出象样的产品,就可技术转让或与人合作搞企业!先把东西准备好,等待机会,否则,有了机会也抓不住!
[9]要学会善于推销自己!不仅要能干,还要能说,能写,善于利用一切机会推销自己,树立自己的品牌形象,很必要!要创造条件让别人了解自己,不然老板怎么知道你能干?外面的投资人怎么相信你?提早把自己推销出去,机会自然会来找你!搞个个人主页是个好注意!!特别是培养自己在行业的名气,有了名气,高薪机会自不在话下,更重要的是有合作的机会...
[10]该出手时便出手!永远不可能有100%把握!!!条件差不多就要大胆去干,去闯出自己的事业,不要犹豫,不要彷徨,干了不一定成功,但至少为下一次冲击积累了经验,不干永远没出息,而且要干成必然要经历失败。不经历风雨,怎么见彩虹,没有人能随随便便成功!
[2]可以做技术,切不可沉湎于技术。千万不可一门心思钻研技术!给自己很大压力,如果你的心思全部放在这上面,那么注定你将成为孔乙己一类的人物!适可而止,因为技术只不过是你今后前途的支柱之一,而且还不是最大的支柱,除非你只愿意到老还是个注册安全工程师!
[3]不要去做技术高手,只去做综合素质高手!在企业里混,我们时常瞧不起某人,说他“什么都不懂,凭啥拿那么多钱,凭啥升官!”这是普遍的典型的注册安全工程师的迂腐之言。某某人很牛吗?人家能上去必然有他的本事,而且是你没有的本事。你想想,老板搞经营那么多年,难道见识不如你这个新兵?人家或许善于管理,善于领会老板意图,善于部门协调等等。因此务必培养自己多方面的能力,包括管理,亲和力,察言观色能力,攻关能力等,要成为综合素质的高手,则前途无量,否则只能躲在角落看显示器!技术以外的技能才是更重要的本事!!从古到今,美国、日本,一律如此!
[4]多交社会三教九流的朋友!不要只和注册安全工程师交往,认为有共同语言,其实更重要的是和其他类人物交往,如果你希望有朝一日当老板或高层管理,那么你整日面对的就是这些人。了解他们的经历,思维习惯,爱好,学习他们处理问题的模式,了解社会各个角落的现象和问题,这是以后发展的巨大的本钱,没有这些以后就会笨手笨脚,跌跌撞撞,遇到重重困难,交不少学费,成功的概率大大降低!
[5]知识涉猎不一定专,但一定要广!多看看其他方面的书,金融,财会,进出口,税务,法律等等,为以后做一些积累,以后的用处会更大!会少交许多学费!
[6]抓住时机向技术管理或市场销售方面的转变!要想有前途就不能一直搞技术,适当时候要转变为管理或销售,前途会更大,以前搞技术也没有白搞,以后还用得着。搞管理可以培养自己的领导能力,搞销售可以培养自己的市场概念和思维,同时为自己以后发展积累庞大的人脉!应该说这才是前途的真正支柱!!!
[7]逐渐克服自己的心里弱点和性格缺陷!多疑,敏感,天真(贬义,并不可爱),犹豫不决,胆怯,多虑,脸皮太薄,心不够黑,教条式思维。。。这些注册安全工程师普遍存在的性格弱点必须改变!很难吗?只在床上想一想当然不可能,去帮朋友守一个月地摊,包准有效果,去实践,而不要只想!不克服这些缺点,一切不可能,甚至连项目经理都当不好--尽管你可能技术不错!
[8]工作的同时要为以后做准备!建立自己的工作环境!及早为自己配置一个工作环境,一方面接触市场,培养市场感觉,同时也积累资金,更重要的是准备自己的产品,咱搞技术的没有钱,只有技术,技术的代表不是学历和证书,而是产品,拿出象样的产品,就可技术转让或与人合作搞企业!先把东西准备好,等待机会,否则,有了机会也抓不住!
[9]要学会善于推销自己!不仅要能干,还要能说,能写,善于利用一切机会推销自己,树立自己的品牌形象,很必要!要创造条件让别人了解自己,不然老板怎么知道你能干?外面的投资人怎么相信你?提早把自己推销出去,机会自然会来找你!搞个个人主页是个好注意!!特别是培养自己在行业的名气,有了名气,高薪机会自不在话下,更重要的是有合作的机会...
[10]该出手时便出手!永远不可能有100%把握!!!条件差不多就要大胆去干,去闯出自己的事业,不要犹豫,不要彷徨,干了不一定成功,但至少为下一次冲击积累了经验,不干永远没出息,而且要干成必然要经历失败。不经历风雨,怎么见彩虹,没有人能随随便便成功!
TCP握手协议(网转)
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:
未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入 ESTABLISHED状态。
Backlog参数:表示未连接队列的最大容纳数目。
SYN-ACK 重传次数服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。
半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。
syn_send a syn=j ---> b
a syn=k ack=j+1
ESTABLISHED a ack=k+1 --->b ESTABLISHED
TCP连接的建立与中止
1.连接的建立
在建立连接的时候,客户端首先向服务器申请打开某一个端口(用SYN段等于1的TCP报文),然后服务器端发回一个ACK报文通知客户端请求报文收到,客户端收到确认报文以后再次发出确认报文确认刚才服务器端发出的确认报文(绕口么),至此,连接的建立完成。这就叫做三次握手。如果打算让双方都做好准备的话,一定要发送三次报文,而且只需要三次报文就可以了。
可以想见,如果再加上TCP的超时重传机制,那么TCP就完全可以保证一个数据包被送到目的地。
2.结束连接
TCP 有一个特别的概念叫做half-close,这个概念是说,TCP的连接是全双工(可以同时发送和接收)连接,因此在关闭连接的时候,必须关闭传和送两个方向上的连接。客户机给服务器一个FIN为1的TCP报文,然后服务器返回给客户端一个确认ACK报文,并且发送一个FIN报文,当客户机回复ACK报文后(四次握手),连接就结束了。
3.最大报文长度
在建立连接的时候,通信的双方要互相确认对方的最大报文长度(MSS),以便通信。一般这个SYN长度是MTU减去固定IP首部和TCP首部长度。对于一个以太网,一般可以达到1460字节。当然如果对于非本地的IP,这个MSS可能就只有536字节,而且,如果中间的传输网络的MSS更佳的小的话,这个值还会变得更小。
4.TCP的状态迁移图(如下:)
说明: ---->实线箭头说明客户的正常状态变迁
---->虚线箭头说明服务器的正常状态变迁
应用进程:说明当应用执行某种操作时发生的状态变迁
收:说明当收到TCP报文段时状态的变迁
发:说明为了进行某个状态变迁要发送的TCP报文段
状态迁移图,包含了两个部分---服务器的状态迁移和客户端的状态迁移,如果从某一个角度出发来看这个图,就会清晰许多,这里面的服务器和客户端都不是绝对的,发送数据的就是客户端,接受数据的就是服务器。
4.1.客户端应用程序的状态迁移图
客户端的状态可以用如下的流程来表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
以上流程是在程序正常的情况下应该有的流程,从图中可以看到,在建立连接时,当客户端收到SYN报文的ACK以后,客户端就打开了数据交互地连接。而结束连接则通常是客户端主动结束的,客户端结束应用程序以后,需要经历FIN_WAIT_1,FIN_WAIT_2等状态,这些状态的迁移就是前面提到的结束连接的四次握手。
4.2.服务器的状态迁移图
服务器的状态可以用如下的流程来表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
在建立连接的时候,服务器端是在第三次握手之后才进入数据交互状态,而关闭连接则是在关闭连接的第二次握手以后(注意不是第四次)。而关闭以后还要等待客户端给出最后的ACK包才能进入初始的状态。
4.3.其他状态迁移
图还有一些其他的状态迁移,这些状态迁移针对服务器和客户端两方面的总结如下
LISTEN->SYN_SENT,对于这个解释就很简单了,服务器有时候也要打开连接的嘛。
SYN_SENT->SYN收到,服务器和客户端在SYN_SENT状态下如果收到SYN数据报,则都需要发送SYN的ACK数据报并把自己的状态调整到SYN收到状态,准备进入ESTABLISHED
SYN_SENT->CLOSED,在发送超时的情况下,会返回到CLOSED状态。
SYN_收到->LISTEN,如果受到RST包,会返回到LISTEN状态。
SYN_收到->FIN_WAIT_1,这个迁移是说,可以不用到ESTABLISHED状态,而可以直接跳转到FIN_WAIT_1状态并等待关闭。
4.4.2MSL等待状态
图里面,有一个TIME_WAIT等待状态,这个状态又叫做2MSL状态,说的是在TIME_WAIT2发送了最后一个ACK数据报以后,要进入 TIME_WAIT状态,这个状态是防止最后一次握手的数据报没有传送到对方那里而准备的(注意这不是四次握手,这是第四次握手的保险状态)。这个状态在很大程度上保证了双方都可以正常结束,但是,问题也来了。
由于插口的2MSL状态(插口是IP和端口对的意思,socket),使得应用程序在 2MSL时间内是无法再次使用同一个插口的,对于客户程序还好一些,但是对于服务程序,例如httpd,它总是要使用同一个端口来进行服务,而在2MSL时间内,启动httpd就会出现错误(插口被使用)。为了避免这个错误,服务器给出了一个平静时间的概念,这是说在2MSL时间内,虽然可以重新启动服务器,但是这个服务器还是要平静的等待2MSL时间的过去才能进行下一次连接。
4.5.FIN_WAIT_2状态
这就是著名的半关闭的状态了,这是在关闭连接时,客户端和服务器两次握手之后的状态。在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种可能是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态。
5.RST,同时打开和同时关闭
RST是另一种关闭连接的方式,应用程序应该可以判断RST包的真实性,即是否为异常中止。而同时打开和同时关闭则是两种特殊的TCP状态,发生的概率很小。
6.TCP服务器设计
UDP的服务器完全不需要所谓的并发机制,它只要建立一个数据输入队列就可以。但是TCP不同,TCP服务器对于每一个连接都需要建立一个独立的进程(或者是轻量级的,线程),来保证对话的独立性。所以TCP服务器是并发的。而且TCP还需要配备一个呼入连接请求队列(UDP服务器也同样不需要),来为每一个连接请求建立对话进程,这也就是为什么各种TCP服务器都有一个最大连接数的原因。而根据源主机的IP和端口号码,服务器可以很轻松的区别出不同的会话,来进行数据的分发。
三次握手:
1:服务器必须准备好接受外来的连接,这通过调用socket,bind,和listen函数来完成,称为被动打开
2:客户通过调用connect 进行主动打开,这引起客户TCP发送一个SYN分节。一般情况下,SYN分节不携带数据,它只含有一个IP头部,一个TCP头部,及可能的TCP选项。
3:服务器必须确认客户的SYN,同时自己也得发送一个SYN分节,包含同一连接中发送数据的一个系列号,服务器以单个分节向客户发送SYN和对客户SYN的ACK.
4:客户确认ACK.
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:
未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入 ESTABLISHED状态。
Backlog参数:表示未连接队列的最大容纳数目。
SYN-ACK 重传次数服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。
半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。
syn_send a syn=j ---> b
a syn=k ack=j+1
ESTABLISHED a ack=k+1 --->b ESTABLISHED
TCP连接的建立与中止
1.连接的建立
在建立连接的时候,客户端首先向服务器申请打开某一个端口(用SYN段等于1的TCP报文),然后服务器端发回一个ACK报文通知客户端请求报文收到,客户端收到确认报文以后再次发出确认报文确认刚才服务器端发出的确认报文(绕口么),至此,连接的建立完成。这就叫做三次握手。如果打算让双方都做好准备的话,一定要发送三次报文,而且只需要三次报文就可以了。
可以想见,如果再加上TCP的超时重传机制,那么TCP就完全可以保证一个数据包被送到目的地。
2.结束连接
TCP 有一个特别的概念叫做half-close,这个概念是说,TCP的连接是全双工(可以同时发送和接收)连接,因此在关闭连接的时候,必须关闭传和送两个方向上的连接。客户机给服务器一个FIN为1的TCP报文,然后服务器返回给客户端一个确认ACK报文,并且发送一个FIN报文,当客户机回复ACK报文后(四次握手),连接就结束了。
3.最大报文长度
在建立连接的时候,通信的双方要互相确认对方的最大报文长度(MSS),以便通信。一般这个SYN长度是MTU减去固定IP首部和TCP首部长度。对于一个以太网,一般可以达到1460字节。当然如果对于非本地的IP,这个MSS可能就只有536字节,而且,如果中间的传输网络的MSS更佳的小的话,这个值还会变得更小。
4.TCP的状态迁移图(如下:)
说明: ---->实线箭头说明客户的正常状态变迁
---->虚线箭头说明服务器的正常状态变迁
应用进程:说明当应用执行某种操作时发生的状态变迁
收:说明当收到TCP报文段时状态的变迁
发:说明为了进行某个状态变迁要发送的TCP报文段
状态迁移图,包含了两个部分---服务器的状态迁移和客户端的状态迁移,如果从某一个角度出发来看这个图,就会清晰许多,这里面的服务器和客户端都不是绝对的,发送数据的就是客户端,接受数据的就是服务器。
4.1.客户端应用程序的状态迁移图
客户端的状态可以用如下的流程来表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
以上流程是在程序正常的情况下应该有的流程,从图中可以看到,在建立连接时,当客户端收到SYN报文的ACK以后,客户端就打开了数据交互地连接。而结束连接则通常是客户端主动结束的,客户端结束应用程序以后,需要经历FIN_WAIT_1,FIN_WAIT_2等状态,这些状态的迁移就是前面提到的结束连接的四次握手。
4.2.服务器的状态迁移图
服务器的状态可以用如下的流程来表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
在建立连接的时候,服务器端是在第三次握手之后才进入数据交互状态,而关闭连接则是在关闭连接的第二次握手以后(注意不是第四次)。而关闭以后还要等待客户端给出最后的ACK包才能进入初始的状态。
4.3.其他状态迁移
图还有一些其他的状态迁移,这些状态迁移针对服务器和客户端两方面的总结如下
LISTEN->SYN_SENT,对于这个解释就很简单了,服务器有时候也要打开连接的嘛。
SYN_SENT->SYN收到,服务器和客户端在SYN_SENT状态下如果收到SYN数据报,则都需要发送SYN的ACK数据报并把自己的状态调整到SYN收到状态,准备进入ESTABLISHED
SYN_SENT->CLOSED,在发送超时的情况下,会返回到CLOSED状态。
SYN_收到->LISTEN,如果受到RST包,会返回到LISTEN状态。
SYN_收到->FIN_WAIT_1,这个迁移是说,可以不用到ESTABLISHED状态,而可以直接跳转到FIN_WAIT_1状态并等待关闭。
4.4.2MSL等待状态
图里面,有一个TIME_WAIT等待状态,这个状态又叫做2MSL状态,说的是在TIME_WAIT2发送了最后一个ACK数据报以后,要进入 TIME_WAIT状态,这个状态是防止最后一次握手的数据报没有传送到对方那里而准备的(注意这不是四次握手,这是第四次握手的保险状态)。这个状态在很大程度上保证了双方都可以正常结束,但是,问题也来了。
由于插口的2MSL状态(插口是IP和端口对的意思,socket),使得应用程序在 2MSL时间内是无法再次使用同一个插口的,对于客户程序还好一些,但是对于服务程序,例如httpd,它总是要使用同一个端口来进行服务,而在2MSL时间内,启动httpd就会出现错误(插口被使用)。为了避免这个错误,服务器给出了一个平静时间的概念,这是说在2MSL时间内,虽然可以重新启动服务器,但是这个服务器还是要平静的等待2MSL时间的过去才能进行下一次连接。
4.5.FIN_WAIT_2状态
这就是著名的半关闭的状态了,这是在关闭连接时,客户端和服务器两次握手之后的状态。在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种可能是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态。
5.RST,同时打开和同时关闭
RST是另一种关闭连接的方式,应用程序应该可以判断RST包的真实性,即是否为异常中止。而同时打开和同时关闭则是两种特殊的TCP状态,发生的概率很小。
6.TCP服务器设计
UDP的服务器完全不需要所谓的并发机制,它只要建立一个数据输入队列就可以。但是TCP不同,TCP服务器对于每一个连接都需要建立一个独立的进程(或者是轻量级的,线程),来保证对话的独立性。所以TCP服务器是并发的。而且TCP还需要配备一个呼入连接请求队列(UDP服务器也同样不需要),来为每一个连接请求建立对话进程,这也就是为什么各种TCP服务器都有一个最大连接数的原因。而根据源主机的IP和端口号码,服务器可以很轻松的区别出不同的会话,来进行数据的分发。
三次握手:
1:服务器必须准备好接受外来的连接,这通过调用socket,bind,和listen函数来完成,称为被动打开
2:客户通过调用connect 进行主动打开,这引起客户TCP发送一个SYN分节。一般情况下,SYN分节不携带数据,它只含有一个IP头部,一个TCP头部,及可能的TCP选项。
3:服务器必须确认客户的SYN,同时自己也得发送一个SYN分节,包含同一连接中发送数据的一个系列号,服务器以单个分节向客户发送SYN和对客户SYN的ACK.
4:客户确认ACK.
一、常用压力测试命令解释:
http_load -p 250 -s 30 -r 40 url.txt
pause
命令解释:模拟250个用户每秒40个请求,持续30秒。
二、
安装,setup:
url.txt
root@172.25.38.70:/home/jackxiang/http_load/http_load-12mar2006# vi url.txt
http://localhost
http://localhost
http://localhost
http://localhost
http://localhost
。
。
。
-parallel 简写-p :含义是并发的用户进程数。
-fetches 简写-f :含义是总计的访问次数
-rate 简写-p :含义是每秒的访问频率
-seconds简写-s :含义是总计的访问时间
http_load -rate 5 -seconds 10 url.txt
/home/jackxiang/http_load/http_load-12mar2006# http_load -rate 5 -seconds 10 url.txt
49 fetches, 1 max parallel, 14553 bytes, in 10 seconds
297 mean bytes/connection
4.9 fetches/sec, 1455.3 bytes/sec
msecs/connect: 0.0360204 mean, 0.067 max, 0.033 min
msecs/first-response: 0.692714 mean, 23.166 max, 0.155 min
HTTP response codes:
code 404 -- 49
阅读全文
http_load -p 250 -s 30 -r 40 url.txt
pause
命令解释:模拟250个用户每秒40个请求,持续30秒。
二、
安装,setup:
root@172.25.**.**:/home/jackxiang/http_load/http_load-12mar2006# make;make install
gcc -Wall -O -c http_load.c
http_load.c: In function ¡®main¡¯:
http_load.c:413: warning: implicit declaration of function ¡®time¡¯
http_load.c: In function ¡®handle_connect¡¯:
http_load.c:937: warning: pointer targets in passing argument 5 of ¡®getsockopt¡¯ differ in signedness
gcc -Wall -O -c timers.c
gcc -Wall -O http_load.o timers.o -s -o http_load
rm -f /usr/local/bin/http_load
cp http_load /usr/local/bin
rm -f /usr/local/man/man1/http_load.1
cp http_load.1 /usr/local/man/man1
gcc -Wall -O -c http_load.c
http_load.c: In function ¡®main¡¯:
http_load.c:413: warning: implicit declaration of function ¡®time¡¯
http_load.c: In function ¡®handle_connect¡¯:
http_load.c:937: warning: pointer targets in passing argument 5 of ¡®getsockopt¡¯ differ in signedness
gcc -Wall -O -c timers.c
gcc -Wall -O http_load.o timers.o -s -o http_load
rm -f /usr/local/bin/http_load
cp http_load /usr/local/bin
rm -f /usr/local/man/man1/http_load.1
cp http_load.1 /usr/local/man/man1
url.txt
root@172.25.38.70:/home/jackxiang/http_load/http_load-12mar2006# vi url.txt
http://localhost
http://localhost
http://localhost
http://localhost
http://localhost
。
。
。
-parallel 简写-p :含义是并发的用户进程数。
-fetches 简写-f :含义是总计的访问次数
-rate 简写-p :含义是每秒的访问频率
-seconds简写-s :含义是总计的访问时间
http_load -rate 5 -seconds 10 url.txt
/home/jackxiang/http_load/http_load-12mar2006# http_load -rate 5 -seconds 10 url.txt
49 fetches, 1 max parallel, 14553 bytes, in 10 seconds
297 mean bytes/connection
4.9 fetches/sec, 1455.3 bytes/sec
msecs/connect: 0.0360204 mean, 0.067 max, 0.033 min
msecs/first-response: 0.692714 mean, 23.166 max, 0.155 min
HTTP response codes:
code 404 -- 49
阅读全文
Mindjet MindManager 思维导图空间快捷方式:Mindjet MindManager 思维导图空间,可以先行记住最需要,Mindjet MindManager 思维导图空间最常用的3个快捷键,然后尽量多的运用它们。熟练了以后,再挑选3个进行练习。
制图
Insert or CTRL + Enter: 添加副主题
Enter: 添加同级主题(向下)
Shift + Enter: 添加同级主题(向上)
CTRL + Shift + Insert: 添加上级主题
CTRL + Shift + Enter: 添加说明
CTRL + Shift + B: 添加边框
F2: 编辑主题内容
CTRL + T: 显示或者隐藏主题说明窗口
CTRL + K: 添加超链接
移动主题
CTRL + Alt + Up arrow: 将主题向上移动一个位置
CTRL + Alt + Down arrow: 将主题向下移动一个位置
CTRL + Alt + Home: 将选中主题移至最高位置
CTRL + Alt + End: 将选中主题移至最低位置
CTRL + Alt + B: 将导图内容平衡分布
格式
CTRL + B: 粗体
CTRL + I: 斜体
CTRL + U: 下划线
CTRL + Space: 清除格式
导航
Arrow Keys: 向主题的上下左右移动
Home: 移动至最高级别主题
End: 移动至最低级别主题
CTRL + Home: 回到中心主题
查看
CTRL + =: 放大画面
CTRL + -: 缩小画面
CTRL + Arrow Keys: 缓慢移动导图画面
CTRL + F3: 收拢所有主题
Alt + F3: 收拢选中主题
F3: 锁定主题
CTRL + D: 在不同级别的主题中浏览
Shift + Alt + (0-9): 显示选中主题的0-9级别的详细内容
Shift + Alt + A: 显示选中主题的所有界别的详细内容
F4: 仅仅显示分支
其他热键
CTRL + F1: 显示或者隐藏工具栏
CTRL + Z: 撤销操作
CTRL + Y: 重复操作
CTRL + A: 全选
CTRL + Shift + A: 选择所有同级项
CTRL + C: 复制
CTRL + V: 黏贴
F7: 拼写检查
对齐同级topic:
用ctrl+鼠标左键选中多个同一级的,在菜单栏目上选排列主题目:左对齐即可。
制图
Insert or CTRL + Enter: 添加副主题
Enter: 添加同级主题(向下)
Shift + Enter: 添加同级主题(向上)
CTRL + Shift + Insert: 添加上级主题
CTRL + Shift + Enter: 添加说明
CTRL + Shift + B: 添加边框
F2: 编辑主题内容
CTRL + T: 显示或者隐藏主题说明窗口
CTRL + K: 添加超链接
移动主题
CTRL + Alt + Up arrow: 将主题向上移动一个位置
CTRL + Alt + Down arrow: 将主题向下移动一个位置
CTRL + Alt + Home: 将选中主题移至最高位置
CTRL + Alt + End: 将选中主题移至最低位置
CTRL + Alt + B: 将导图内容平衡分布
格式
CTRL + B: 粗体
CTRL + I: 斜体
CTRL + U: 下划线
CTRL + Space: 清除格式
导航
Arrow Keys: 向主题的上下左右移动
Home: 移动至最高级别主题
End: 移动至最低级别主题
CTRL + Home: 回到中心主题
查看
CTRL + =: 放大画面
CTRL + -: 缩小画面
CTRL + Arrow Keys: 缓慢移动导图画面
CTRL + F3: 收拢所有主题
Alt + F3: 收拢选中主题
F3: 锁定主题
CTRL + D: 在不同级别的主题中浏览
Shift + Alt + (0-9): 显示选中主题的0-9级别的详细内容
Shift + Alt + A: 显示选中主题的所有界别的详细内容
F4: 仅仅显示分支
其他热键
CTRL + F1: 显示或者隐藏工具栏
CTRL + Z: 撤销操作
CTRL + Y: 重复操作
CTRL + A: 全选
CTRL + Shift + A: 选择所有同级项
CTRL + C: 复制
CTRL + V: 黏贴
F7: 拼写检查
对齐同级topic:
用ctrl+鼠标左键选中多个同一级的,在菜单栏目上选排列主题目:左对齐即可。
http://www.umiwi.com/video/detail1475
技术手艺积累,创业的积累的软实力是不一样的。
技术手艺积累,创业的积累的软实力是不一样的。
usr/include文件夹下有众多的头文件,编写c++时经常要include一些头文件,程序连接头文件时是不是在include文件夹的下面的所有文件中寻找
有没有人给我讲讲这些运行的机制
编译C++时include的那些头文件是由编译器决定路径及寻找顺序的,/usr/include这种肯定在编译器寻找的路径内。如果不在编译器指定路径内,则需要手动使用-I选项指定头文件路径
程序只是在编译时需要用到这些头文件,链接时直接链接dll,需要用-l选项指定需要链接哪些.so文件,指定链接文件名时省略前面的lib与后面的.so,比如链接libparted.so(这是一个与磁盘分区相关的共享库)应该写为 -lparted。
例子:
g++ test.cpp -I/home/ -ldl -o test
是指编译test.cpp源程序,这个源程序include进来的头文件可以先去/home/文件夹下查找,如果没有再去系统路径(就是你前面说的/usr/include这样的)下查找。链接阶段请链接上libdl.so这个共享库,最后生成的可执行文件叫test
如:
g++ -o a a.cpp -L/full-path-to-mysql/lib -I/full-path-to-mysql/include -lmysqlclient
请问:这里的-L/full-path-to-mysql/lib 中的L是什么意思?8 W/ O- Q* w! A$ b
还有I/ 的I是什么东东。* T! g3 g& L0 k4 h' u
是盘符吗?; ?" k$ Q3 G) o" w3 b8 Z
有没有必要修改/httpd.conf中的东西,修改什么地方?
L是库文件(lib)目录,I是头文件(include)目录。
有没有人给我讲讲这些运行的机制
编译C++时include的那些头文件是由编译器决定路径及寻找顺序的,/usr/include这种肯定在编译器寻找的路径内。如果不在编译器指定路径内,则需要手动使用-I选项指定头文件路径
程序只是在编译时需要用到这些头文件,链接时直接链接dll,需要用-l选项指定需要链接哪些.so文件,指定链接文件名时省略前面的lib与后面的.so,比如链接libparted.so(这是一个与磁盘分区相关的共享库)应该写为 -lparted。
例子:
g++ test.cpp -I/home/ -ldl -o test
是指编译test.cpp源程序,这个源程序include进来的头文件可以先去/home/文件夹下查找,如果没有再去系统路径(就是你前面说的/usr/include这样的)下查找。链接阶段请链接上libdl.so这个共享库,最后生成的可执行文件叫test
如:
g++ -o a a.cpp -L/full-path-to-mysql/lib -I/full-path-to-mysql/include -lmysqlclient
请问:这里的-L/full-path-to-mysql/lib 中的L是什么意思?8 W/ O- Q* w! A$ b
还有I/ 的I是什么东东。* T! g3 g& L0 k4 h' u
是盘符吗?; ?" k$ Q3 G) o" w3 b8 Z
有没有必要修改/httpd.conf中的东西,修改什么地方?
L是库文件(lib)目录,I是头文件(include)目录。
我也不是很懂,参考:http://blog.csdn.net/janders/archive/2006/02/27/611081.aspx阅读全文
功能说明:建立或修改备存文件,或是从备存文件中抽取文件。
语 法:ar[-dmpqrtx][cfosSuvV][a<成员文件>][b<成员文件>][i<成员文件>][备存文件][成员文件]
补充说明:ar可让您集合许多文件,成为单一的备存文件。在备存文件中,所有成员文件皆保有原来的属性与权限。
参 数:
指令参数
-d 删除备存文件中的成员文件。
-m 变更成员文件在备存文件中的次序。
-p 显示备存文件中的成员文件内容。
-q 将问家附加在备存文件末端。
-r 将文件插入备存文件中。
-t 显示备存文件中所包含的文件。
-x 自备存文件中取出成员文件。
选项参数
a<成员文件> 将文件插入备存文件中指定的成员文件之后。
b<成员文件> 将文件插入备存文件中指定的成员文件之前。
c 建立备存文件。
f 为避免过长的文件名不兼容于其他系统的ar指令指令,因此可利用此参数,截掉要放入备存文件中过长的成员文件名称。
i<成员文件> 将问家插入备存文件中指定的成员文件之前。
o 保留备存文件中文件的日期。
s 若备存文件中包含了对象模式,可利用此参数建立备存文件的符号表。
S 不产生符号表。
u 只将日期较新文件插入备存文件中。
v 程序执行时显示详细的信息。
V 显示版本信息。
ar用来管理一种文档。这种文档中可以包含多个其他任意类别的文件。这些被包含的文件叫做这个文档的成员。ar用来向这种文档中添加、删除、解出成员。成员的原有属性(权限、属主、日期等)不会丢失。
实际上通常只有在开发中的目标连接库是这种格式的,所以尽管不是,我们基本可以认为ar是用来操作这种目标链接库(.a文件)的。
ar的常用用法见正文。
1、创建库文件
我 不知道怎么创建一个空的库文件。好在这个功能好像不是很需要。通常人们使用“ar cru liba.a a.o"这样的命令来创建一个库并把a.o添加进去。"c"关键字告诉ar需要创建一个新库文件,如果没有指定这个标志则ar会创建一个文件,同时会给出 一个提示信息,"u"用来告诉ar如果a.o比库中的同名成员要新,则用新的a.o替换原来的。但是我发现这个参数也是可有可无的,可能是不同版本的ar 行为不一样吧。实际上用"ar -r liba.a a.o"在freebsd5上面始终可以成功。
2、加入新成员
使用"ar -r liba.a b.o"即可以将b.o加入到liba.a中。默认的加入方式为append,即加在库的末尾。"r"关键字可以有三个修饰符"a", "b"和"i"。
"a"表示after,即将新成员加在指定成员之后。例如"ar -ra a.c liba.a b.c"表示将b.c加入liba.a并放在已有成员a.c之后;
"b"表示before,即将新成员加在指定成员之前。例如"ar -rb a.c liba.a b.c";
"i"表示insert,跟"b"作用相同。
3、列出库中已有成员
"ar -t liba.a"即可。如果加上"v"修饰符则会一并列出成员的日期等属性。
4、删除库中成员
"ar -d liba.a a.c"表示从库中删除a.c成员。如果库中没有这个成员ar也不会给出提示。如果需要列出被删除的成员或者成员不存在的信息,就加上"v"修饰符。
5、从库中解出成员
"ar -x liba.a b.c"
6、调整库中成员的顺序
使用"m"关键字。与"r"关键字一样,它也有3个修饰符"a","b", "i"。如果要将b.c移动到a.c之前,则使用"ar -mb a.c liba.a b.c"
来源:http://hi.baidu.com/ever__love/blog/item/e714c6aadebbf7bccb130c8d.html
语 法:ar[-dmpqrtx][cfosSuvV][a<成员文件>][b<成员文件>][i<成员文件>][备存文件][成员文件]
补充说明:ar可让您集合许多文件,成为单一的备存文件。在备存文件中,所有成员文件皆保有原来的属性与权限。
参 数:
指令参数
-d 删除备存文件中的成员文件。
-m 变更成员文件在备存文件中的次序。
-p 显示备存文件中的成员文件内容。
-q 将问家附加在备存文件末端。
-r 将文件插入备存文件中。
-t 显示备存文件中所包含的文件。
-x 自备存文件中取出成员文件。
选项参数
a<成员文件> 将文件插入备存文件中指定的成员文件之后。
b<成员文件> 将文件插入备存文件中指定的成员文件之前。
c 建立备存文件。
f 为避免过长的文件名不兼容于其他系统的ar指令指令,因此可利用此参数,截掉要放入备存文件中过长的成员文件名称。
i<成员文件> 将问家插入备存文件中指定的成员文件之前。
o 保留备存文件中文件的日期。
s 若备存文件中包含了对象模式,可利用此参数建立备存文件的符号表。
S 不产生符号表。
u 只将日期较新文件插入备存文件中。
v 程序执行时显示详细的信息。
V 显示版本信息。
ar用来管理一种文档。这种文档中可以包含多个其他任意类别的文件。这些被包含的文件叫做这个文档的成员。ar用来向这种文档中添加、删除、解出成员。成员的原有属性(权限、属主、日期等)不会丢失。
实际上通常只有在开发中的目标连接库是这种格式的,所以尽管不是,我们基本可以认为ar是用来操作这种目标链接库(.a文件)的。
ar的常用用法见正文。
1、创建库文件
我 不知道怎么创建一个空的库文件。好在这个功能好像不是很需要。通常人们使用“ar cru liba.a a.o"这样的命令来创建一个库并把a.o添加进去。"c"关键字告诉ar需要创建一个新库文件,如果没有指定这个标志则ar会创建一个文件,同时会给出 一个提示信息,"u"用来告诉ar如果a.o比库中的同名成员要新,则用新的a.o替换原来的。但是我发现这个参数也是可有可无的,可能是不同版本的ar 行为不一样吧。实际上用"ar -r liba.a a.o"在freebsd5上面始终可以成功。
2、加入新成员
使用"ar -r liba.a b.o"即可以将b.o加入到liba.a中。默认的加入方式为append,即加在库的末尾。"r"关键字可以有三个修饰符"a", "b"和"i"。
"a"表示after,即将新成员加在指定成员之后。例如"ar -ra a.c liba.a b.c"表示将b.c加入liba.a并放在已有成员a.c之后;
"b"表示before,即将新成员加在指定成员之前。例如"ar -rb a.c liba.a b.c";
"i"表示insert,跟"b"作用相同。
3、列出库中已有成员
"ar -t liba.a"即可。如果加上"v"修饰符则会一并列出成员的日期等属性。
4、删除库中成员
"ar -d liba.a a.c"表示从库中删除a.c成员。如果库中没有这个成员ar也不会给出提示。如果需要列出被删除的成员或者成员不存在的信息,就加上"v"修饰符。
5、从库中解出成员
"ar -x liba.a b.c"
6、调整库中成员的顺序
使用"m"关键字。与"r"关键字一样,它也有3个修饰符"a","b", "i"。如果要将b.c移动到a.c之前,则使用"ar -mb a.c liba.a b.c"
来源:http://hi.baidu.com/ever__love/blog/item/e714c6aadebbf7bccb130c8d.html
在WEB开发中,数据库的数据读写和传输一向是瓶颈,在此基础上的解决方案基本都是数据库连接层的设计,一个公司数据库连接层的牛B与否可以标识这个公司的全局规划的“工艺水平”到达一个什么样了。下面的内容来自明查暗访,决无BS之意,旨在提供给需要统一规划整体架构的架构师一个帮助。
1.人人网
参考:http://ugc.renren.com/2009/12/28/renren-ice-problem/
关键词:ice中间层,统一配置数据源,开发者不关心分库分表
与很多大型的网站一样,人人网的系统全部是由开源软件构建的。使用Nginx做前端接入,resin做容器,Memcached做通用 cache,MySQL做数据库,使用Linux操作系统。
除了上述的部分外,人人网还有一个与众不同的中间层。中间层以服务的形式存在,位于MySQL和resin中间,提供高并发低成本的数据访问层。
2.百度
参考:http://wenku.baidu.com/view/9daa2b8102d276a200292e9c.html
关键词:dbproxy,服务器都是flash卡,DBA与开发者都不关心分裤分表(半自动)
百度的dbproxy利器,将mysql的管理半自动化,HA等功能一应俱全,再加上SSD等硬件支持,性能相当不一般。
3.盛大-技术保障中心
参考:网友
关键词:无中间件,每个系统一个数据库,开发者严重关心分库分表
4.新浪
参考:网友
关键词:无中间件 分表要开发者自己做
这个在前期是有常连接的设计的:如Sina早期的企业邮箱等,后面php的出现慢慢给取消掉了rpc等实现的长连接。modifyed by Jackxiang
5.金山
参考:网友
关键词:无中间件 分表要开发者自己做
6.腾讯
参考:腾讯大讲堂45-解剖TTC
关键词:Tencent Table Cache
TTC是提供高速数据访问服务的通用cache server。特点是采用epoll和异步状态机模式提高并发能力。TTC看上去是一个数据库缓冲层,由于资料有限,只能如此分析。
–感谢胖子和呵呵哥提供线索支持
7.淘宝、支付宝
参考:http://wenku.baidu.com/view/f36d620c844769eae009edba.html
关键词:JBoss作为中间件,有数据路由层,数据库 Oracle 与 MySQL
在网络上许多文档里都有提到阿里内部是有一数据路由层的,另外JBoss的使用也使得他们轻便不少(可惜当年哥在淘宝时只搞的是搜索,不使用DB)
–感谢Fenng提供线索支持
8.阿里巴巴B2B
自己实现了db proxy,自定义分库及路由规则,有client版也有server版;分布式数据库原型
–感谢Brave提供线索支持
调查中采访了许多人,比较遗憾的是腾讯的布道者 太少,基本上只有一个呵呵哥可以问,可他工作中还没有用到数据库,在此特进行BS。
来源:http://www.54chen.com/_linux_/china-internet-db-report.html
1.人人网
参考:http://ugc.renren.com/2009/12/28/renren-ice-problem/
关键词:ice中间层,统一配置数据源,开发者不关心分库分表
与很多大型的网站一样,人人网的系统全部是由开源软件构建的。使用Nginx做前端接入,resin做容器,Memcached做通用 cache,MySQL做数据库,使用Linux操作系统。
除了上述的部分外,人人网还有一个与众不同的中间层。中间层以服务的形式存在,位于MySQL和resin中间,提供高并发低成本的数据访问层。
2.百度
参考:http://wenku.baidu.com/view/9daa2b8102d276a200292e9c.html
关键词:dbproxy,服务器都是flash卡,DBA与开发者都不关心分裤分表(半自动)
百度的dbproxy利器,将mysql的管理半自动化,HA等功能一应俱全,再加上SSD等硬件支持,性能相当不一般。
3.盛大-技术保障中心
参考:网友
关键词:无中间件,每个系统一个数据库,开发者严重关心分库分表
4.新浪
参考:网友
关键词:无中间件 分表要开发者自己做
这个在前期是有常连接的设计的:如Sina早期的企业邮箱等,后面php的出现慢慢给取消掉了rpc等实现的长连接。modifyed by Jackxiang
5.金山
参考:网友
关键词:无中间件 分表要开发者自己做
6.腾讯
参考:腾讯大讲堂45-解剖TTC
关键词:Tencent Table Cache
TTC是提供高速数据访问服务的通用cache server。特点是采用epoll和异步状态机模式提高并发能力。TTC看上去是一个数据库缓冲层,由于资料有限,只能如此分析。
–感谢胖子和呵呵哥提供线索支持
7.淘宝、支付宝
参考:http://wenku.baidu.com/view/f36d620c844769eae009edba.html
关键词:JBoss作为中间件,有数据路由层,数据库 Oracle 与 MySQL
在网络上许多文档里都有提到阿里内部是有一数据路由层的,另外JBoss的使用也使得他们轻便不少(可惜当年哥在淘宝时只搞的是搜索,不使用DB)
–感谢Fenng提供线索支持
8.阿里巴巴B2B
自己实现了db proxy,自定义分库及路由规则,有client版也有server版;分布式数据库原型
–感谢Brave提供线索支持
调查中采访了许多人,比较遗憾的是腾讯的布道者 太少,基本上只有一个呵呵哥可以问,可他工作中还没有用到数据库,在此特进行BS。
来源:http://www.54chen.com/_linux_/china-internet-db-report.html