epoll讲解

目录
  1. epoll接口函数
    1. 创建epoll实例
    2. 管理epoll事件
    3. 等待epoll事件
  2. epoll实例
  3. mac下的epoll
  4. epoll源码实现

epoll接口函数

头文件: #include<sys/epoll.h>
可以通过man epoll查看对应的帮助信息
最大描述符限制:/proc/sys/fs/epoll/max_user_watches

创建epoll实例

1
2
int epoll_create(int size);
int epoll_create1(int flag);

epoll_create中,size只是给内核的一个维数提示,并不是队列中的最大数,Now days, size is ignored since Linux 2.6.8
epoll_create1中flag取值如下:

  • 0:epoll_create1 == epoll_create (size argument is dropped)
  • EPOLL_CLOEXEC:含义同open函数的O_CLOEXEC选项;当执行execve创建新进程时,打开的描述符自动关闭
    p.s: 当使用完毕时,需要调用close关闭epoll实例句柄

    管理epoll事件

1
int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);

参数说明:

  • epfd: epoll_create返回的epoll实例
  • op: 对应的操作
  • fd: 监听的fd
  • event: 监听的事件
    其中op取值如下:
  • EPOLL_CTL_ADD:添加监听的事件
  • EPOLL_CTL_DEL:删除监听的事件
  • EPOLL_CTL_MOD:修改监听的事件
    struct epoll_event定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
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 */
};

其中events可以包含以下事件类型:

  • EPOLLIN: 描述符可读
  • EPOLLOUT: 描述符可写
  • EPOLLRDHUP(since Linux 2.6.17): 流套接字对端关闭连接或者关闭写端
  • EPOLLPRI: 紧急数据可读
  • EPOLLERR: 描述符发生错误,该事件由内核一直监听(比如connect套接字失败会返回EPOLLERR)
  • EPOLLHUP: 文件秒杀符被中断,该事件由内核一直监听
  • EPOLLET: 开启边缘触发,默认是水平触发
  • EPOLLONESHOT: 一个事件发生并读取之后,fd自动不再监控;若要重新监控需要使用EPOLL_CTL_MOD重新设置
    返回值: 成功返回0,失败返回-1并设置errno

    等待epoll事件

1
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

参数说明:

  • epfd: epoll_create返回的epoll实例
  • events: 存储epoll_event的数组地址
  • maxevents: 最大事件的数量,需>0
  • timeout: 等待的最长时间
    返回值:
    成功时返回就绪的监听文件描述符数;当超出timeout指定的时间后如果无就绪的文件描述符,返回0;发生错误时返回-1并设置errno
    另外,Linux kernel 2.6.19 引入了epoll_pwait,可以在等待时设置信号掩码,其使用方式类似pselect

some problems:

  1. epoll 怎么判断是connect请求还是有数据可读?
    ans: 判断events[i].data.fd == listen_fd
  2. read 返回值说明:
  • return -1 and errno == EAGAIN: 数据已经读完,没有可读数据
  • return 0: end of file,对端关闭连接

关于水平触发(Level-Triggered)和边缘触发(Edge-Triggered)
当缓冲区有数据可读时,ET会触发一次事件,之后就不会再触发;而LT只要我们没有读完缓冲区的数据,事件就会一直触发。
推荐使用的epoll ET方式如下:

  1. 设置fd为非阻塞
  2. 当调用read或write读写时,在其返回-1,且errno == EAGAIN 后再调用epoll_wait等待
    tips:
    ET模式只能用于设置了O_NONBLOCK的fd,而LT则同时支持同步及异步。如果将ET模式应用与阻塞情况,将出现如下问题:
    当对端send 2 byte数据,而服务端只读取了1 byte后再去调用epoll_wait,这时将不产生读事件。直到对端又有数据发送过来,epoll_wait才会再次返回
    补充:
    Q:当又有事件产生时会怎么样,原来的数据还在吗?
    A:原来的数据还在socket缓冲区

    epoll实例

    epoll使用参考:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
static int
create_and_bind (char *port)
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int s, sfd;
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */
hints.ai_flags = AI_PASSIVE; /* All interfaces */
s = getaddrinfo (NULL, port, &hints, &result);
if (s != 0)
{
fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s));
return -1;
}
for (rp = result; rp != NULL; rp = rp->ai_next)
{
sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
s = bind (sfd, rp->ai_addr, rp->ai_addrlen);
if (s == 0)
{
/* We managed to bind successfully! */
break;
}
close (sfd);
}
if (rp == NULL)
{
fprintf (stderr, "Could not bind\n");
return -1;
}
freeaddrinfo (result);
return sfd;
}
static int
make_socket_non_blocking (int sfd)
{
int flags, s;
flags = fcntl (sfd, F_GETFL, 0);
if (flags == -1)
{
perror ("fcntl");
return -1;
}
flags |= O_NONBLOCK;
s = fcntl (sfd, F_SETFL, flags);
if (s == -1)
{
perror ("fcntl");
return -1;
}
return 0;
}
#define MAXEVENTS 64
int
main (int argc, char *argv[])
{
int sfd, s;
int efd;
struct epoll_event event;
struct epoll_event *events;
if (argc != 2)
{
fprintf (stderr, "Usage: %s [port]\n", argv[0]);
exit (EXIT_FAILURE);
}
sfd = create_and_bind (argv[1]);
if (sfd == -1)
abort ();
s = make_socket_non_blocking (sfd);
if (s == -1)
abort ();
s = listen (sfd, SOMAXCONN);
if (s == -1)
{
perror ("listen");
abort ();
}
efd = epoll_create1 (0);
if (efd == -1)
{
perror ("epoll_create");
abort ();
}
event.data.fd = sfd;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);
if (s == -1)
{
perror ("epoll_ctl");
abort ();
}
/* Buffer where events are returned */
events = calloc (MAXEVENTS, sizeof event);
/* The event loop */
while (1)
{
int n, i;
n = epoll_wait (efd, events, MAXEVENTS, -1);
for (i = 0; i < n; i++)
{
if ((events[i].events & EPOLLERR) ||
(events[i].events & EPOLLHUP) ||
(!(events[i].events & EPOLLIN)))
{
/* An error has occured on this fd, or the socket is not
ready for reading (why were we notified then?) */
fprintf (stderr, "epoll error\n");
close (events[i].data.fd);
continue;
}
else if (sfd == events[i].data.fd)
{
/* We have a notification on the listening socket, which
means one or more incoming connections. */
while (1)
{
struct sockaddr in_addr;
socklen_t in_len;
int infd;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
in_len = sizeof in_addr;
infd = accept (sfd, &in_addr, &in_len);
if (infd == -1)
{
if ((errno == EAGAIN) ||
(errno == EWOULDBLOCK))
{
/* We have processed all incoming
connections. */
break;
}
else
{
perror ("accept");
break;
}
}
s = getnameinfo (&in_addr, in_len,
hbuf, sizeof hbuf,
sbuf, sizeof sbuf,
NI_NUMERICHOST | NI_NUMERICSERV);
if (s == 0)
{
printf("Accepted connection on descriptor %d "
"(host=%s, port=%s)\n", infd, hbuf, sbuf);
}
/* Make the incoming socket non-blocking and add it to the
list of fds to monitor. */
s = make_socket_non_blocking (infd);
if (s == -1)
abort ();
event.data.fd = infd;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);
if (s == -1)
{
perror ("epoll_ctl");
abort ();
}
}
continue;
}
else
{
/* We have data on the fd waiting to be read. Read and
display it. We must read whatever data is available
completely, as we are running in edge-triggered mode
and won't get a notification again for the same
data. */
int done = 0;
while (1)
{
ssize_t count;
char buf[512];
count = read (events[i].data.fd, buf, sizeof buf);
if (count == -1)
{
/* If errno == EAGAIN, that means we have read all
data. So go back to the main loop. */
if (errno != EAGAIN)
{
perror ("read");
done = 1;
}
break;
}
else if (count == 0)
{
/* End of file. The remote has closed the
connection. */
done = 1;
break;
}
/* Write the buffer to standard output */
s = write (1, buf, count);
if (s == -1)
{
perror ("write");
abort ();
}
}
if (done)
{
printf ("Closed connection on descriptor %d\n",
events[i].data.fd);
/* Closing the descriptor will make epoll remove it
from the set of descriptors which are monitored. */
close (events[i].data.fd);
}
}
}
}
free (events);
close (sfd);
return EXIT_SUCCESS;
}
  • 客户端代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
int create_and_connect(char * port)
{
if(NULL == port)
{
return -1;
}
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo *result;
int ret = getaddrinfo(NULL, port, &hints, &result);
if(ret != 0)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(ret));
return -1;
}
struct addrinfo *rp;
int cfd;
for(rp = result; rp != NULL; rp = rp->ai_next)
{
cfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(-1 == cfd)
{
continue;
}
//client connect
ret = connect(cfd, rp->ai_addr, rp->ai_addrlen);
if(0 == ret)
{
break;
}
close(cfd);
}
if(NULL == rp)
{
fprintf(stderr, "connect to port failed!\n");
return -1;
}
freeaddrinfo(result);
return cfd;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
fprintf(stderr, "Usage: %s [port]\n", argv[0]);
exit(-1);
}
//clinet send something
int cfd = create_and_connect(argv[1]);
if(-1 == cfd)
{
fprintf(stderr, "create_and_connect failed\n");
return -1;
}
char *pData = "Client hello!";
int dataLen = strlen(pData);
send(cfd, pData, dataLen, 0);
sleep(1);
send(cfd, pData, dataLen, 0);
return 0;
}

mac下的epoll

mac os不支持epoll,其使用kqueue实现(类似epoll),头文件 sys/event.h
linkhttps://zhuanlan.zhihu.com/p/21375144

epoll源码实现

epoll源码实现分析
epoll源码实现分析(整理)

参考博客:Linux epoll 详解

我的vimrc快捷操作

目录
  1. leader键
  2. 自动保存及加载工程设置
    1. 保存viminfo及session
    2. 恢复viminfo及session
  3. 缩进可视化
  4. cpp和h文件间切换
  5. 显示tag窗口
  6. cscope支持
  7. 显示当前目录文件列表
  8. 显示及隐藏minibufexplorer窗口
  9. 在整个目录下查找匹配的关键字
  10. lookupfile查找
  11. youcompleteme快捷键
  12. 窗口移动操作

leader键

mapleader = “;”

自动保存及加载工程设置

在工程目录下创建workspace.vim配置文件,其中可以设置项目path等信息

保存viminfo及session

ss (save session)

恢复viminfo及session

rs (read session)

缩进可视化

vimrc中配置自动打开,可以使用i进行开关

cpp和h文件间切换

sw (switch)

显示tag窗口

or ilt (identifier list by tag)

cscope支持

自动导入工程目录下的cscope.out文件
set cscopequickfix=s-,c-,d-,i-,t-,e- 使用quickfix窗口显示搜索结果
浏览结束后按 或者 可以回到跳转前的位置。
快捷操作:
如果每次查找都要输入一长串命令的话还真是件讨人厌的事情, Cscope的帮助
手册中推荐了一些快捷键的用法, 下面是其中一组, 也是我用的, 将下面的内容添
加到~/.vimrc中, 并重启vim:

1
2
3
4
5
6
7
8
nmap <C-_>s :cs find s <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>g :cs find g <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>c :cs find c <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>t :cs find t <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>e :cs find e <C-R>=expand("<cword>")<CR><CR>
nmap <C-_>f :cs find f <C-R>=expand("<cfile>")<CR><CR>
nmap <C-_>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
nmap <C-_>d :cs find d <C-R>=expand("<cword>")<CR><CR>

当光标停在某个你要查找的词上时, 按下g, 就是查找该对象的定义, 其他的同理. 按这种组合键有一点技巧,按了后要马上按下一个键,否则屏幕一闪就回到
nomal状态了
g的按法是先按”Ctrl+Shift+-“, 然后很快再按”s”

显示当前目录文件列表

(用NERDTree插件显示)

显示及隐藏minibufexplorer窗口

bl (buffer explorer)
buffer间切换 —— ctrl+Tab(向后),ctrl+shift+Tab(向前)

在整个目录下查找匹配的关键字

sp (search project) [CtrlSF插件]
感觉这个插件和cscope功能有重叠的部分

lookupfile查找

  • lt (LUTags)
  • lb (LUBufs)
  • lw (LUWalk)
    分别对应查找tag,buffer及目录文件

    youcompleteme快捷键

  • jc (jump to declaration)
  • jd (jump to definition)
  • ; (智能补全)

    窗口移动操作

    ctrl+[h|j|k|l] (分别对应于左上下右,与方向键一致)

vim配置进阶

目录
  1. 保存及应用工程配置
  2. 使用ctags
  3. 缓冲区及文件、tag查找
  4. cscope使用
  5. 自动刷新工程中的tags

保存及应用工程配置

  1. 设置vim搜索路径
    如set path=.,/usr/include,/usr/local/include,当使用find, gf, ctrl+W f(水平分割窗口打开)命令时vim会去path变量设置的目录下搜索.使用时可以把需要做的设置写到workspace.vim文件中,然后在打开工程的时候加载
  2. 保存vim session及viminfo
    使用会话(session)和viminfo,可以把你编辑环境保存下来,然后在你下次启动vim后,可以再恢复回这个环境。
    session
    会话(session)中保存了所有窗口的视图,外加全局设置。可以使用‘set sessionoptions’选项设定。缺省的‘sessionoptions’选项包括: “blank,buffers,curdir,folds,help,options,tabpages,winsize”
    command: 使用mksession [file]命令来保存session,使用source [file]命令来导入保存的session
    viminfo
    viminfo中保存了命令行历史(history)、搜索历史(search)、输入行历史、非空的寄存器内容(register)、文件的位置标记(mark)、缓冲区列表、全局变量等信息。
    command: 使用wviminfo [file]命令保存viminfo,使用rviminfo命令载入保存的viminfo
  3. 自动导入工程配置
    每次退出vim时都要手动保存viminfo及session文件,启动时再进行导入,岂不是很麻烦,如果能支持自动导入的话就very nice了。没问题,我们可以通过修改vimrc文件来实现这个目的.相关vimrc配置如下(可结合自身情况更改):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
" 设置自动加载当前目录的工程设置
if filereadable("workspace.vim")
source workspace.vim
endif
" 设置vim启动时自动读取session及viminfo信息
if filereadable("workspace.session")
source workspace.session
endif
if filereadable("workspace.viminfo")
rviminfo workspace.viminfo
endif
" 设置vim退出时自动保存工程配置
if filereadable("workspace.vim") "表示需要保存,防止不必要的保存
au VimLeave * mksession workspace.session
au VimLeave * wviminfo workspace.viminfo
endif

使用ctags

使用ctags命令:ctags -R . 命令生成tags文件,然后使用set tags=tags导入,可以使用vimrc设置自动导入

缓冲区及文件、tag查找

项目中,当打开的文件太多说,知道当前打开的文件名是一项有用的功能,这个可以通过minibufexpl实现,效果如下:
pic

vim中可以使用lookupfile插件进行tag, buffer, 文件及目录搜索,其对应的指令分别如下:

  • 缓冲区查找:LUBufs
  • 目录查找:LUWalk
  • tag查找:LUTags

cscope使用

如果你需求查找函数调用或者变量使用的地方,ctags就无能为力了,这时候就得用cscope了。
用法:
cscope默认只生成.c文件的索引,如果是c++或者java等其他语言,需要自行增加索引文件表。可以使用如下命令:
find . -name "*.h" -o -name "*.c" -o -name "*.cc" > cscope.files
cscope -bkq -i cscope.files
然后在工程vim中执行: cscope add cscope.out,导入cscope索引。之后就可以使用cscope操作了,其操作命令如下:
man cscope或者vim中执行help cscope

1
2
3
4
5
6
7
8
cs find s ---- 查找C语言符号,即查找函数名、宏、枚举值等出现的地方
cs find g ---- 查找函数、宏、枚举等定义的位置,类似ctags所提供的功能
cs find d ---- 查找本函数调用的函数
cs find c ---- 查找调用本函数的函数
cs find t ---- 查找指定的字符串
cs find e ---- 查找egrep模式,相当于egrep功能,但查找速度快多了
cs find f ---- 查找并打开文件,类似vimfind功能
cs find i ---- 查找包含本文件的文件

使用时,可以把cscope的查找结果输出到quickfix窗口,需要在~/.vimrc中加入下面这行:
set cscopequickfix=s-,c-,d-,i-,t-,e-
p.s:
打开quickfix —— copen
关闭quickfix —— cclose
查找下一个 —— cn
查找上一个 —— cp
浏览位置间跳转 —— ctrl+o(往前),ctrl+i(往后)

自动刷新工程中的tags

未完待续

可以点击my vimrc访问我的vimrc配置

openssl命令

目录
  1. 生成证书
  2. 证书签名
  3. 证书吊销
  4. 验证证书
  5. 生成RSA密钥对
  6. RSA加密算法

生成证书

请参考使用openssl生成证书

证书签名

请参考使用openssl生成证书

证书吊销

  1. 吊销证书
    openssl ca -revoke newcerts/username.pem -config openssl.cnf
  2. 重新生成证书吊销列表
    openssl ca -config openssl.cnf -gencrl -out crl/ca.crl
  3. 生成hash码链接文件
    ln -s ca.crl `openssl crl -hash -noout -in ca.crl`.r0
  4. 把ca.crl及hash码文件拷贝到应用证书吊销列表文件夹

验证证书

openssl verify -CAfile cacert.pem servercert.pem

生成RSA密钥对

  1. 生成私钥
    openssl genrsa -out rsa_private_key.pem 1024
  2. 生成公钥
    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
  3. 查看私钥信息
    openssl rsa -in rsa_private_key.pem -text -noout

示例如下,其中生成的moduls前两位需要去掉:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ openssl rsa -in rsa_private_key.pem -text -noout
Private-Key: (512 bit)
modulus:
00:cb:23:6d:74:e6:bf:cb:89:a1:66:52:ca:5f:c2:
76:23:30:60:52:bc:bd:20:a6:25:cc:8e:61:73:46:
01:f4:60:09:45:2a:db:fa:34:33:06:8b:61:85:8e:
c7:1c:1c:77:1d:cd:f2:ab:e2:af:f2:e8:c9:03:ec:
18:2a:72:d9:af
publicExponent: 65537 (0x10001)
privateExponent:
62:c7:2b:66:78:fe:32:7f:0e:58:af:51:71:17:22:
53:22:26:f4:94:8a:72:e1:d7:e7:8c:24:9e:e5:1f:
f6:30:0e:e3:e5:bc:d2:4f:79:c5:21:72:dd:3f:9b:
b5:71:52:1c:0e:d7:0e:d6:46:bd:dc:af:d2:23:95:
cd:08:18:a1
prime1:
00:ec:9a:67:ec:ae:cd:9e:48:f9:fd:27:f1:01:fa:
14:38:5b:f2:55:a1:1e:16:42:c0:31:a5:af:b9:22:
f9:37:dd
prime2:
00:db:ca:b2:38:54:d8:64:d3:74:db:bf:a2:00:fc:
c8:45:d8:f4:1b:05:32:c5:29:8f:56:70:0a:c2:50:
56:24:fb
exponent1:
31:ab:60:71:c1:68:8c:f8:08:f2:ea:35:a0:12:9d:
b8:0f:25:5a:70:8e:5e:61:f8:f2:f3:33:66:8c:3f:
01:49
exponent2:
3f:6a:4b:63:9f:6f:54:20:02:be:88:9b:18:87:d6:
cc:f8:5c:ee:12:e0:e4:2c:2a:94:38:fd:91:b5:16:
35:d3
coefficient:
7f:68:40:1f:63:8e:60:f3:0e:e6:e0:9c:84:ce:3e:
89:1b:e3:62:01:23:44:70:94:ff:ea:c1:b5:d4:a4:
ac:50

RSA加密算法

  1. 生成密钥对,即RAS结构
  2. 公钥持有端使用RSA_public_encrypt和RSA_public_decrypt进行加解密(openssl中的函数)
  3. 私钥持有端使用RSA_private_encrypt和RSA_private_decrypt进行加解密

一个工程的Makefile模版

Makefile作为Linux下的源码编译规则说明,配合make命令使用,可以快速编译出库及可执行文件。经过整理,已经将一个简单工程的Makefile代码归档到github上,工程代码及Makefile见:

Makefile-template

工程中包含三个Makefile(最外层的称为总控makefile),各个makefile中有相关的注释说明,有需要的自行到https://github.com/chhy2009/Makefile-template.git 下载。

make install 时指定安装路径:
export DESTDIR=install_dir , 然后 make install

make时存在库依赖问题,解决方法如下:
export PKG_CONFIG_PATH=/.../software_name/lib/pkgconfig/
即设置被依赖库路径到PKG_CONFIG_PATH变量

编译动态库

  • 由源文件直接编译
    gcc–shared –fpic –o libtest.so test.c

  • 由.o文件编译
    gcc -shared *.o -o libtest.so

编译静态库

先gcc源文件为.o,再执行 ar –rc libtest.a .o打包成静态库

网络相关命令汇总

网络问题的处理方法

一般来说,如果访问不了某个URL的话,可能是网络存在某些问题,这时可以用下面的步骤进行排查:

  1. ifconfig
    查看网络和IP地址是否ok
  2. route -n
    查看下路由表,有时候需要手动增加路由选项,才能ping同url
  3. ping Gateway 的 IP
    有时候由于网关设置错误或者网线接的有问题,导致网关不通
  4. 查看dns服务器是否配置正确
    使用nslookup命令或dig命令查看 域名对应的ip地址
  5. 跟踪网络包流向
    使用traceroute命令查看IP数据包的流向,判断在哪个链路节点出现问题

另外,介绍下网络相关的其它命令:

  • ip 很强大的命令,整合了ifconfig和route命令的功能的同时,还有其它功能
  • tcpdump Linux下的抓包工具
  • iwconfig 无线网络配置
  • iwlist 查看无线网络相关信息
  • iw 用于无线网络信息查看和配置
  • ifup/ifdown 设置网络接口的启用
  • netstat 查看端口使用情况
  • ftp/sftp/tftp/ ssh/telnet 用于连接远程端,传输文件和登陆
本站总访问量