-j linux
2017-03-29 21:05:00 weixin_33843947 阅读数 14
2953340-ea10e4633b6dd22a.png
Paste_Image.png
2953340-20ab529875e293eb.png
Paste_Image.png
2953340-c35474a73c942b3d.png
Paste_Image.png
2953340-26afeb095786097c.png
Paste_Image.png
2953340-9d200bc03989bcdb.png
Paste_Image.png
2953340-4f46a227a2eb0453.png
Paste_Image.png
2953340-1e27ea37383b50f1.png
Paste_Image.png
2953340-a41ca64dcf505472.png
Paste_Image.png
2953340-9ba9690a306412f9.png
Paste_Image.png
2953340-d25d18c697c0a6be.png
Paste_Image.png
2953340-d476a5dd3b5d910e.png
Paste_Image.png
2953340-1fa6ab8090e3f832.png
Paste_Image.png
2953340-c036a05443dc280e.png
Paste_Image.png
2953340-c90e05f08bed5d50.png
Paste_Image.png

推荐使用centos32 64更占内存


2953340-09cfb3f40d55ca65.png
Paste_Image.png
2953340-0ea3d58d12fa4c55.png
Paste_Image.png
2953340-b4a0de57a29a3c93.png
Paste_Image.png
2953340-2140541bac4ee30a.png
Paste_Image.png
2953340-fbd3f79a96693388.png
Paste_Image.png

推荐使用桥接


2953340-ccee60dd0474be34.png
Paste_Image.png

虚拟机使用技巧
快照

克隆

2953340-2a86d73633a9507d.png
Paste_Image.png
2953340-f6ed120794347091.png
Paste_Image.png
2953340-b49af2a125fde374.png
Paste_Image.png
2953340-4728cd9a4c747658.png
Paste_Image.png
2017-08-19 18:18:28 smilejiasmile 阅读数 255

一、TCP、IP概述

 


1、tcp/ip 模型 4 层

  • 应用层{ http 超文本传输协议  ftp 文件传输协议  telnet 远程登录  ssh 安全外壳协议  stmp 简单邮件发送、pop3 收邮件}
  • 传输层{ tcp 传输控制协议,  udp 用户数据包协议}
  • 网络层{ip 网际互联协议 icmp 网络控制消息协议 igmp 网络组管理协议}
  • 网络接口层{arp 地址转换协议,rarp 反向地址转换协议, mpls 多协议标签交换}
  • TCP 协议: 传输控制协议 面向连接的协议 能保证传输安全可靠 速度慢(有 3 次握手)
  • UDP 协议: 用户数据包协议 非面向连接 速度快 不可靠
  • 通常是 ip 地址后面跟上端口号: ip 用来定位主机 port 区别应用(进程)  http 的端口号 80 ssh-->22 telnet-->23 ftp-->21 用户自己定义的通常要大于 1024

 

2、 TCP/IP 协议族的每一层的作用

 

  • 网络接口层: 负责将二进制流转换为数据帧, 并进行数据帧的发送和接收。要注意的是数据帧是独立的网络信息传输单元。
  • 网络层: 负责将数据帧封装成 IP 数据报, 并运行必要的路由算法。
  • 传输层: 负责端对端之间的通信会话连接和建立。 传输协议的选择根据数据传输方式而定。
  • 应用层: 负责应用程序的网络访问, 这里通过端口号来识别各个不同的进程。

 

3、 TCP协议

     TCP 是 TCP/IP 体系中面向连接的运输层协议, 它提供全双工和可靠交付的服务。 它采用许多机制来确保端到端结点之间的可靠数据传输, 如采用序列号、 确认重传、 滑动窗口等。

 

  • 三次握手协议

                                          

 

 

4、协议的选择

 

     对数据要求高可靠性的应用需选择 TCP 协议, 如验证、 密码字段的传送都是不允许出错的, 而对数据的可靠性要求不那么高的应用可选择 UDP 传送。

     TCP 协议在传送过程中要使用三次握手、重传确认等手段来保证数据传输的可靠性。 使用 TCP 协议会有较大的时延, 因此不适合对实时性要求较高的应用, 如 VOIP、 视频监控等。 相反, UDP 协议则在这些应用中能发挥很好的作用。

 

二、网络的相关概念

 

1、套接字

 

     网络通信,归根到底还是进程间的通信(不同计算机上的进程间通信)。网络地址,即IP 地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底是和网络中的哪一个进程进行通信, 因此套接口中还需要包括其他的信息, 也就是端口号(PORT) 。一个端口号一次只能分配给一个进程,使用端口号和网络地址的组合可以唯一的确定整个网络中的一个网络进程。

 

     例如, 如网络中某一台计算机的 IP 为 10.92.20.160, 操作系统分配给计算机中某一应用程序进程的端口号为 1500, 则此时 10.92.20.160 1500 就构成了一个套接口。

 

     端口号的范围从 0~65535。一种是常用的应用程序固定使用的“周知的端口”,其值一般为0~1023。http 的端口号是 80, ftp 为 21, ssh 为 22, telnet 为 23 等。 还有一类是用户自己定义的, 通常是大于 1024 的整型值。

ipv4 地址: 32bit, 4 字节, 通常采用点分十进制记法(如128.11.3.31),但是在网络中,socket 编程中使用的则是二进制值, 这就需要将这两个数值进行转换。

 

2、ip地址分类

 

                                                  

 

 

3、socket 类型

 

(1) 流式 socket(SOCK_STREAM) 用于 TCP 通信

     流式套接字提供可靠的、 面向连接的通信流; 它使用 TCP 协议, 从而保证了数据传输的正确性和顺序性。

 

(2) 数据报 socket(SOCK_DGRAM) 用于 UDP 通信

     数据报套接字定义了一种无连接的服务, 数据通过相互独立的报文进行传输, 是无序的, 并且不保证是可靠、 无差错的。 它使用数据报协议 UDP。

 

(3) 原始 socket(SOCK_RAW) 用于新的网络协议实现的测试等

原始套接字允许对底层协议如 IP 或 ICMP 进行直接访问, 它功能强大但使用较为不便, 主要用于一些协议的开发。

 

4、socket信息数据结构

 

struct sockaddr         ---->网络传输常用

{

     unsigned short sa_family;          /*地址族*/

     char sa_data[14];             /*14 字节的协议地址, 包含该 socket 的 IP 地址和端口号。 */

};

 

struct sockaddr_in      ---->编程常用

{

     short int sa_family;               /*地址族*/

     unsigned short int sin_port;       /*端口号*/

     struct in_addr sin_addr;           /*IP 地址*/

     unsigned char sin_zero[8];        

     /*填充 0 以保持与 struct sockaddr 同样大小*/

};

 

struct in_addr

{

     unsigned long int

     s_addr;

     /* 32 位 IPv4 地址, 网络字节序 */

};

 

头文件<netinet/in.h>

sa_family: AF_INET --->IPv4 协议   AF_INET6 ---> IPv6 协议

 

5、数据存储优先顺序的转换

 

     计算机数据存储有两种字节优先顺序: 高位字节优先(称为大端模式) 和低位字节优先(称为小端模式)。

低地址存储数据的低字节, 高地址存储数据的高字节 ---> 小端模式

高地址存储数据的低字节, 低地址存储数据高字节    --->  大端模式

而端口号和 IP 地址都是以网络字节序存储的, 不是主机字节序, 网络字节序都是大端模式。故需要进行相互转化。

 

四个函数:

htons(),ntohs(),htonl()和 ntohl().这四个地址分别实现网络字节序和主机字节序的转化, 这里的 h代表 host,n 代表 network, s 代表 short, l 代表 long。 通常 16 位的 IP 端口号用 s 代表。

 

6、地址格式转化

 

     用户在表达网络地址时采用的是点分十进制表示的数值,socket 编程中使用的则是 32 位的网络字节序的二进制值, 这就需要将这两个数值进行转换。Ipv4 中用到的函数有 inet_aton()、 inet_addr()和 inet_ntoa(),而 IPV4 和 Ipv6 兼容的函数有 inet_pton()和 inet_ntop()。

 

IPv4 的函数原型:

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

     int inet_aton(const char *straddr, struct in_addr

     *addrptr);

     char *inet_ntoa(struct in_addr inaddr);

     in_addr_t inet_addr(const char *straddr);

     // in_addr_t 就是 unsigned long int ,代

表 s_addr函数 inet_aton(): 将点分十进制数的 IP 地址转换成为网络字节序的 32 位二进制数值。 返回值:成功,则返回 1, 不成功返回 0.

     参数 straddr: 存放输入的点分十进制数 IP 地址字符串。

     参数 addrptr: 传出参数, 保存网络字节序的 32 位二进制数值。

     函数 inet_ntoa(): 将网络字节序的 32 位二进制数值转换为点分十进制的 IP 地址。

     函数 inet_addr(): 功能与 inet_aton 相同, 但是结果传递的方式不同。 inet_addr()若成功则返回32 位二进制的网络字节序地址。

 

IPv4 和 IPv6 的函数原型:

#include <arpa/inet.h>

     int inet_pton(int family, const char *src, void *dst);

     const char *inet_ntop(int family, const void *src, char *dst, socklen_t len);

 

7、地址名字地址转化

 

函数原型:

 

#include <netdb.h>

struct hostent* gethostbyname(const char* hostname);

struct hostent* gethostbyaddr(const char* addr, size_t len,

int family);

 

结构体:

struct hostent

{

     char *h_name;          /*正式主机名*/

     char **h_aliases;      /*主机别名*/

     int h_addrtype;        /*主机 IP 地址类型 IPv4 为 AF_INET*/

     int h_length;          /*主机 IP 地址字节长度, 对于 IPv4 是 4 字节, 即 32 位*/

     char **h_addr_list;      /*主机的 IP 地址列表*/

}

 

8、网络编程函数---汇总

 

1. 头文件包含:

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<unistd.h>

#include<string.h>

#include <stdio.h>

#include <stdlib.h>

   

TCP服务器端:

2. socket 函数: 生成一个套接口描述符。

 

原型: int socket(int domain,int type,int protocol);

参数: domain{ AF_INET: Ipv4 网络协议 AF_INET6: IPv6 网络协议}  type{tcp: SOCK_STREAM udp: SOCK_DGRAM}

protocol指定 socket 所使用的传输协议编号。 通常为 0.

返回值: 成功则返回套接口描述符, 失败返回-1。

 

常用实例: int sfd = socket(AF_INET, SOCK_STREAM, 0);

if(sfd == -1){perror("socket");exit(-1);}

 

3. bind 函数: 用来绑定一个端口号和 IP 地址, 使套接口与指定的端口号和 IP 地址相关联。

 

原型: int bind(int sockfd,struct sockaddr * my_addr,int addrlen);

参数: sockfd为前面 socket 的返回值。

my_addr为结构体指针变量

 

4. listen 函数: 使服务器的这个端口和 IP 处于监听状态, 等待网络中某一客户机的连接请求。 如果客户

端有连接请求, 端口就会接受这个连接。

 

原型: int listen(int sockfd,int backlog);

参数: sockfd为前面 socket 的返回值.即 sfd

backlog指定同时能处理的最大连接要求, 通常为 10 或者 5。 最大值可设至 128

返回值: 成功则返回 0, 失败返回-1

 

常用实例: if(listen(sfd, 10) == -1)

{perror("listen");close(sfd);exit(-1);}

 

5. accept 函数: 接受远程计算机的连接请求, 建立起与客户机之间的通信连接。 服务器处于监听状态时,如果某时刻获得客户机的连接请求, 此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时再处理客户机的连接请求。当 accept 函数接受一个连接时, 会返回一个新的 socket 标识符,以后的数据传输和读取就要通过这个新的 socket 编号来处理,原来参数中的 socket 也可以继续使用, 继

服务器跟一个客户端连接成功, 会有两个套接字。)续监听其它客户机的连接请求。

 

原型: int accept(int s,struct sockaddr * addr,int * addrlen);

参数: s为前面 socket 的返回值.即 sfd。addr为结构体指针变量,和 bind 的结构体是同种类型的, 系统会把远程主机的信息(远程主机的地址和端口号信息) 保存到这个指针所指的结构体中。addrlen表示结构体的长度,为整型指针。

返回值: 成功则返回新的 socket 处理代码 new_fd, 失败返回-1

 

常用实例:

struct sockaddr_in clientaddr;

memset(&clientaddr, 0, sizeof(struct sockaddr));

int addrlen = sizeof(struct sockaddr);

int new_fd = accept(sfd, (struct sockaddr*)&clientaddr, &addrlen);

if(new_fd == -1)

     {

          perror("accept");close(sfd);exit(-1);

     }

     printf("%s %d success connect\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));

 

6. recv 函数: 用新的套接字来接收远端主机传来的数据, 并把数据存到由参数 buf 指向的内存空间

原型: int recv(int sockfd,void *buf,int len,unsigned int flags);

 

参数:sockfd为前面 accept 的返回值.即 new_fd, 也就是新的套接字。

buf表示缓冲区

len表示缓冲区的长度

flags通常为 0

返回值: 成功则返回实际接收到的字符数, 可能会少于你所指定的接收长度。 失败返回-1。

 

常用实例:

char buf[512] = {0};

if(recv(new_fd, buf, sizeof(buf), 0) == -1)

{

     perror("recv");close(new_fd);close(sfd);exit(-1);

}

puts(buf);

 

7. send 函数: 用新的套接字发送数据给指定的远端主机

原型: int send(int s,const void * msg,int len,unsigned int flags);

参数: s为前面 accept 的返回值.即 new_fd

msg一般为常量字符串     len表示长度      flags通常为 0

返回值: 成功则返回实际传送出去的字符数, 可能会少于你所指定的发送长度。 失败返回-1

 

常用实例: if(send(new_fd, "hello", 6, 0) == -1)

{perror("send");close(new_fd);close(sfd);exit(-1);}

 

8. close 函数: 当使用完文件后若已不再需要则可使用 close()关闭该文件, 并且 close()会让数据写回磁盘,并释放该文件所占用的资源

 

原型: int close(int fd);

参数: fd为前面的 sfd,new_fd

返回值: 若文件顺利关闭则返回 0, 发生错误时返回-1

 

常用实例: close(new_fd);

close(sfd);

 

TCP客户端:

1. connect 函数: 用来请求连接远程服务器, 将参数 sockfd 的 socket 连至参数 serv_addr 指定的服务器

IP 和端口号上去。

 

原型: int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

参数: sockfd为前面 socket 的返回值, 即 sfd

serv_addr为结构体指针变量, 存储着远程服务器的 IP 与端口号信息。

addrlen表示结构体变量的长度

返回值: 成功则返回 0, 失败返回-1

 

常用实例

struct sockaddr_in seraddr;//请求连接服务器

memset(&seraddr, 0, sizeof(struct sockaddr));

seraddr.sin_family = AF_INET;

seraddr.sin_port = htons(8888); //服务器的端口号

seraddr.sin_addr.s_addr = inet_addr("192.168.0.101"); //服务器的 ip

if(connect(sfd, (struct sockaddr*)&seraddr, sizeof(struct sockaddr)) == -1)

{

     perror("connect");

     close(sfd);

     exit(-1);

}

 

UDP:

1、sendto()函数原型

 

int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);

 

该函数比 send()函数多了两个参数, to 表示目地机的 IP 地址和端口号信息, 而 tolen 常常被赋值为sizeof (struct sockaddr)。 sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。

 

2、recvfrom()函数原型:

 

int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);

 

from 是一个 struct sockaddr 类型的变量,该变量保存连接机的 IP 地址及端口号。fromlen 常置为 sizeof(struct sockaddr)。 当 recvfrom()返回时,fromlen 包含实际存入 from 中的数据字节数。 Recvfrom()函数返回接收到的字节数或当出现错误时返回-1, 并置相应的 errno。

 

二、浅析Socket、HTTP、SOAP、Restful、PHP、JSP、H5演变和区别

 

Socket、HTTP、SOAP 等区别

2017-03-31 21:42:00 weixin_33725722 阅读数 15
2953340-1f3454491ca38be5.png
Paste_Image.png
2953340-eab9b9829412ec76.png
Paste_Image.png
2953340-b97080649c3cc351.png
Paste_Image.png
2953340-c21fee31a0332236.png
Paste_Image.png
2953340-c04d8241bddfbf96.png
Paste_Image.png
2953340-6b4bfc8c9473ed0c.png
Paste_Image.png
2953340-c0f03d410035f4eb.png
Paste_Image.png
2953340-e693f2108a59367a.png
Paste_Image.png
2953340-d6d6cba7a030a053.png
Paste_Image.png
2953340-0cc2c636cf4f5f48.png
2953340-f808fdbe2dc8532f.png
Paste_Image.png
2018-12-11 18:54:55 qq_35608277 阅读数 73

用make -j带一个参数,可以把项目在进行并行编译,比如在一台双核的机器上,完全可以用make -j4,让make最多允许4个编译命令同时执行,这样可以更有效的利用CPU资源。

在多核CPU上,适当的进行并行编译还是可以明显提高编译速度的。但并行的任务不宜太多,一般是以CPU的核心数目的两倍为宜。

REF
https://www.freemindworld.com/blog/2010/100105_make_complie_process_faster.shtml

2019-06-04 09:32:54 don_chiang709 阅读数 69

转自:https://www.freemindworld.com/blog/2010/100105_make_complie_process_faster.shtml

项目越来越大,每次需要重新编译整个项目都是一件很浪费时间的事情。Research了一下,找到以下可以帮助提高速度的方法,总结一下。

  • 1. tmpfs

有人说在Windows下用了RAMDisk把一个项目编译时间从4.5小时减少到了5分钟,也许这个数字是有点夸张了,不过粗想想,把文件放到内存上做编译应该是比在磁盘上快多了吧,尤其如果编译器需要生成很多临时文件的话。

这个做法的实现成本最低,在Linux中,直接mount一个tmpfs就可以了。而且对所编译的工程没有任何要求,也不用改动编译环境。

mount -t tmpfs tmpfs ~/build -o size=1G

用2.6.32.2的Linux Kernel来测试一下编译速度:

用物理磁盘:40分16秒

用tmpfs:39分56秒

呃……没什么变化。看来编译慢很大程度上瓶颈并不在IO上面。但对于一个实际项目来说,编译过程中可能还会有打包等IO密集的操作,所以只要可能,用tmpfs是有益无害的。当然对于大项目来说,你需要有足够的内存才能负担得起这个tmpfs的开销。

  • make -j

既然IO不是瓶颈,那CPU就应该是一个影响编译速度的重要因素了。

用make -j带一个参数,可以把项目在进行并行编译,比如在一台双核的机器上,完全可以用make -j4,让make最多允许4个编译命令同时执行,这样可以更有效的利用CPU资源。

还是用Kernel来测试:

用make: 40分16秒

用make -j4:23分16秒

用make -j8:22分59秒

由此看来,在多核CPU上,适当的进行并行编译还是可以明显提高编译速度的。但并行的任务不宜太多,一般是以CPU的核心数目的两倍为宜。

不过这个方案不是完全没有cost的,如果项目的Makefile不规范,没有正确的设置好依赖关系,并行编译的结果就是编译不能正常进行。如果依赖关系设置过于保守,则可能本身编译的可并行度就下降了,也不能取得最佳的效果。

  • ccache

ccache用于把编译的中间结果进行缓存,以便在再次编译的时候可以节省时间。这对于玩Kernel来说实在是再好不过了,因为经常需要修改一些Kernel的代码,然后再重新编译,而这两次编译大部分东西可能都没有发生变化。对于平时开发项目来说,也是一样。为什么不是直接用make所支持的增量编译呢?还是因为现实中,因为Makefile的不规范,很可能这种“聪明”的方案根本不能正常工作,只有每次make clean再make才行。

安装完ccache后,可以在/usr/local/bin下建立gcc,g++,c++,cc的symbolic link,链到/usr/bin/ccache上。总之确认系统在调用gcc等命令时会调用到ccache就可以了(通常情况下/usr/local/bin会在PATH中排在/usr/bin前面)。

继续测试:

用ccache的第一次编译(make -j4):23分38秒

用ccache的第二次编译(make -j4):8分48秒

用ccache的第三次编译(修改若干配置,make -j4):23分48秒

看来修改配置(我改了CPU类型…)对ccache的影响是很大的,因为基本头文件发生变化后,就导致所有缓存数据都无效了,必须重头来做。但如果只是修改一些.c文件的代码,ccache的效果还是相当明显的。而且使用ccache对项目没有特别的依赖,布署成本很低,这在日常工作中很实用。

可以用ccache -s来查看cache的使用和命中情况:

cache directory                   /home/lifanxi/.ccache
cache hit                           7165
cache miss                         14283
called for link                       71
not a C/C++ file                     120
no input file                       3045
files in cache                     28566
cache size                          81.7 Mbytes
max cache size                     976.6 Mbytes

可以看到,显然只有第二编次译时cache命中了,cache miss是第一次和第三次编译带来的。两次cache占用了81.7M的磁盘,还是完全可以接受的。

  • distcc

一台机器的能力有限,可以联合多台电脑一起来编译。这在公司的日常开发中也是可行的,因为可能每个开发人员都有自己的开发编译环境,它们的编译器版本一般是一致的,公司的网络也通常具有较好的性能。这时就是distcc大显身手的时候了。

使用distcc,并不像想象中那样要求每台电脑都具有完全一致的环境,它只要求源代码可以用make -j并行编译,并且参与分布式编译的电脑系统中具有相同的编译器。因为它的原理只是把预处理好的源文件分发到多台计算机上,预处理、编译后的目标文件的链接和其它除编译以外的工作仍然是在发起编译的主控电脑上完成,所以只要求发起编译的那台机器具备一套完整的编译环境就可以了。

distcc安装后,可以启动一下它的服务:

/usr/bin/distccd --daemon --allow 10.64.0.0/16

默认的3632端口允许来自同一个网络的distcc连接。

然后设置一下DISTCC_HOSTS环境变量,设置可以参与编译的机器列表。通常localhost也参与编译,但如果可以参与编译的机器很多,则可以把localhost从这个列表中去掉,这样本机就完全只是进行预处理、分发和链接了,编译都在别的机器上完成。因为机器很多时,localhost的处理负担很重,所以它就不再“兼职”编译了。

export DISTCC_HOSTS=&quot;localhost 10.64.25.1 10.64.25.2 10.64.25.3&quot;

然后与ccache类似把g++,gcc等常用的命令链接到/usr/bin/distcc上就可以了。

在make的时候,也必须用-j参数,一般是参数可以用所有参用编译的计算机CPU内核总数的两倍做为并行的任务数。

同样测试一下:

一台双核计算机,make -j4:23分16秒

两台双核计算机,make -j4:16分40秒

两台双核计算机,make -j8:15分49秒

跟最开始用一台双核时的23分钟相比,还是快了不少的。如果有更多的计算机加入,也可以得到更好的效果。

在编译过程中可以用distccmon-text来查看编译任务的分配情况。distcc也可以与ccache同时使用,通过设置一个环境变量就可以做到,非常方便。

总结一下:

  • tmpfs: 解决IO瓶颈,充分利用本机内存资源
  • make -j: 充分利用本机计算资源
  • distcc: 利用多台计算机资源
  • ccache: 减少重复编译相同代码的时间

这些工具的好处都在于布署的成本相对较低,综合利用这些工具,就可以轻轻松松的节省相当可观的时间。上面介绍的都是这些工具最基本的用法,更多的用法可以参考它们各自的man page。

 

 

 

没有更多推荐了,返回首页