背景:为何数组的首地址当指针传入函数时,得传入数组的长度?在函数体内的其实是通过数组名初始化的指针形参,故不能在函数中通过 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度。所以一般将数组名作为形参传入函数时,也会同时传递一个数组长度的参数。为何指针长度是8位,而不是4位?因为系统是64位的(8字节,64位系统)。

数组名一旦传入函数,再用sizeof(数组名,也就是首地址),其得出的值变为8了,不再是1024了,实践如下:
vi fwrite.c

#./fwrite
1)直接在变量申明段里访问数组长度值:sizeof的数组名buffer=1024
2)!!returnArrPointerLen函数返回buffer数组首地址到函数里后长度值就不等于1024了,等于:8
3)returnArrPointerLen函数传入指向数组buffer首地址返回buffer长度和申明数组长度不一样等于8
4)sizeof buf=8
5)strlen buf=44
6)sizeof buf=8
7)strlen buf=34

总之,一旦将数组首地址传入函数,那么其长度就变成了指针长度了,而32位系统和64位系统指针分别对应的是4和8:

#./sizeofarr
1)指向数组首地址,数组的长度是: 20
2)用指针指向数组的首地址长度是: 8
3)试图求下数组第一个键值的空间大小sizeof(number)=4
4)再试图通过sizeof(number)/sizeof(number[0]得出5? 5
数组的元素分别是:
1 2 3 4 5


在c/c++中我们一般都用 sizeof(数组名)/sizeof(数组元素类型) 来计算数组的长度,其中 sizeof(数组名) 计算的是数组占用的存储大小。同时,一般我们认为数组名和指针就是一回事,最近写程序时将数组名作为指针形参传入函数,想在函数中用 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度时却出了错,最后发现原来是sizeof(数组名)和sizeof(指针)的区别导致的,于是写了段代码测试了一下:



输出结果:

数组名:40
指针:8
指针引用:8
函数指针形参:8

可以看到,当sizeof的参数是数组名时,计算的是整个数组的存储大小;当sizeof的参数是指针时,计算的是指针的大小(8字节,64位系统)。而且,可以定义对指针的引用,但却不能用数组名来作为指针引用的右值,可见数组名和指针还是有区别的。同时,将数组名作为实参传入函数时,因为形参是指针,所以在函数体内的其实是通过数组名初始化的指针形参,故不能在函数中通过 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度。所以一般将数组名作为形参传入函数时,也会同时传递一个数组长度的参数。

来自:http://blog.csdn.net/u012707739/article/details/75732159


C语言fwrite怎么写入文件?
==================来自:https://zhidao.baidu.com/question/1893763120275364500.html==================
我设了一个字符串char rgb[3]; 然后用fwrite(&rgb,3,1,file)和fwrite(&rgb,1,3,file)写入一个bmp文件 这两个得到了相同的东西 而fwrite(&rgb,3,2,file)得到的是rgb的三个数据+三个CC(204) 请问fwrite是怎么读取rgb的数据的? 是不是按照首地址++? fwrite(&rgb,3,2,file)里前三个数读完了然后想要读取rgb[3] [4]和[5]但是读取的是乱码 所以默认显示为CC?
fwrite函数在写文件时是以二进制形式进行的。
函数原型:int fwrite(char *ptr, unsigned size, unsigned n, FILE *fp);

功       能:将ptr所指向的n*size个字节输出到fp所指向的文件中

返 回  值:写到fp文件中的数据项的个数

实践:
背景:主进程退出后,子进程没有退出,http://jackxiang.com/post/6937/
父进程退出后,子进程还在,怎么杀死,暂别说平滑过渡死,先杀死子进程得了,当父进程意外退出时,比如coredump了,根本没机会主动发送信号或pipe等消息的。用了prctl 这个调用,实践来自@http://blog.csdn.net/gavin_new/article/details/73432013:
1)子进程加上在子进程中给父进程设置当父进程退出时子进程收到的信号:
    /* 子进程中给父进程设置当父进程退出时子进程收到的信号 */
    prctl(PR_SET_PDEATHSIG, SIGHUP);
  
2)主进程退出退知子进程的信号量执行:
    if (sig == SIGHUP){  
          printf("child recv SIGHUP..\n");//主进程退出退知子进程  
          //kill_signal_master(sig);  //不要这行也成,&kill_signal_worker部分应该作了处理。
    }
3)实践是否真杀死了?
#ps -f -C  multepoolser
UID        PID  PPID  C STIME TTY          TIME CMD
root     14096 13713  0 15:58 pts/1    00:00:00 [httpmut: master process] master process
apache   14097 14096 99 15:58 pts/1    00:00:02 [httpmut: worker process] worker process
#kill -TERM 14096
#ps -f -C  multepoolser   #子进程也被杀死退出了。
UID        PID  PPID  C STIME TTY          TIME CMD
========================具体代码=========================
httpmut父进程处理kill信号:

处理函数:


子进程线号处理侦听函数:


子进程信号处理:


  Linux 中创建子进程是相当方便的,通过fork调用即可。当子进程退出时,要给父进程发送SIG_CHLD信号,是为了父进程回收子进程的资源,方便管理的目的。 但是当父进程退出后,一般是不会通知子进程的,父进程会将自己的所有子进程过继给init进程。

但是,在实际的项目中,我们有这样的需求: 如果父进程退出后,希望能通知子进程退出。

我们知道,可以利用进程间通信机制,在父进程退出前主动发送信号或pipe或其他手段告知子进程自己退出了。

但是,当父进程意外退出时,比如coredump了,根本没机会主动发送信号或pipe等消息的。

这时怎么办呢?

我们发现 prctl 这个调用, 通过man prctl:


据此, 我们可以在子进程中给父进程设置当父进程退出时子进程收到的信号。

代码如下:

通过测试,如果去掉 prctl调用,当父进程发生段错误退出后,子进程依然继续运行。 如果去掉signal调用,即子进程不捕获SIG_HUP信号,当父进程退出后依然会退出,只是退出的有些不优雅罢了。
来自:http://blog.csdn.net/gavin_new/article/details/73432013
实践如下:
#./prctl
in parent.
in child...
memcpy ...
child recv SIGHUP..
in child...
child exit...
段错误(吐核)


二、主进程退出对子线程的影响,线程退出是什么样的一个情况呢?源码来自:http://originlee.com/2015/04/08/influence-of-main-threads-exiting-to-child-thread/
cat ./pthreadtest.c

gcc -o pthreadtest pthreadtest.c -lpthread -lmemcached  
#./pthreadtest
child loops
child loops
child loops
child loops
child loops
...
child loops
child loops
child loops
main exit
运行上面的代码,会发现程序在打印一定数量的「child loops」和一句「main exit」之后退出,并且在退出之前的最后一句打印是「main exit」。

按照他们的逻辑,你看,因为主线程在打印完「main exit」后退出了,然后子线程也跟着退出了,所以随后就没有子线程的打印了。

但其实这里是混淆了进程退出和线程退出的概念了。实际的情况是主线程中的main函数执行完ruturn后弹栈,然后调用glibc库函数exit,exit进行相关清理工作后调用_exit系统调用退出该进程。所以,这种情况实际上是因为进程运行完毕退出导致所有的线程也都跟着退出了,并非是因为主线程的退出导致子线程也退出。
Linux线程模型
实际上,posix线程和一般的进程不同,在概念上没有主线程和子线程之分(虽然在实际实现上还是有一些区分),如果仔细观察apue或者unp等书会发现基本看不到「主线程」或者「子线程」等词语,在csapp中甚至都是用「对等线程」一词来描述线程间的关系。

在Linux 2.6以后的posix线程都是由用户态的pthread库来实现的。在使用pthread库以后,在用户视角看来,每一个tast_struct就对应一个线程(tast_struct原本是内核对应一个进程的结构),而一组线程以及他们所共同引用的一组资源就是进程。从Linux 2.6开始,内核有了线程组的概念,tast_struct结构中增加了一个tgid(thread group id)字段。getpid(获取进程号)通过系统调用返回的也是tast_struct中的tgid,所以tgid其实就是进程号。而tast_struct中的线程号pid字段则由系统调用syscall(SYS_gettid)来获取。

当线程收到一个kill致命信号时,内核会将处理动作施加到整个线程组上。为了应付「发送给进程的信号」和「发送给线程的信号」,tast_struct里面维护了两套signal_pending,一套是线程组共用的,一套是线程独有的。通过kill发送的致命信号被放在线程组共享的signal_pending中,可以任意由一个线程来处理。而通过pthread_kill发送的信号被放在线程独有的signal_pending中,只能由本线程来处理。

关于线程与信号,apue有这么几句:

每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的。这意味着尽管单个线程可以阻止某些信号,但当线程修改了与某个信号相关的处理行为以后,所有的线程都必须共享这个处理行为的改变。这样如果一个线程选择忽略某个信号,而其他的线程可以恢复信号的默认处理行为,或者是为信号设置一个新的处理程序,从而可以撤销上述线程的信号选择。

如果信号的默认处理动作是终止该进程,那么把信号传递给某个线程仍然会杀掉整个进程。

例如一个程序a.out创建了一个子线程,假设主线程的线程号为9601,子线程的线程号为9602(它们的tgid都是9601),因为默认没有设置信号处理程序,所以如果运行命令kill 9602的话,是可以把9601和9602这个两个线程一起杀死的。如果不知道Linux线程背后的故事,可能就会觉得遇到灵异事件了。

另外系统调用syscall(SYS_gettid)获取的线程号与pthread_self获取的线程号是不同的,pthread_self获取的线程号仅仅在线程所依赖的进程内部唯一,在pthread_self的man page中有这样一段话:

Thread IDs are guaranteed to be unique only within a process. A thread ID may be reused after a terminated thread has been joined, or a detached thread has terminated.

所以在内核中唯一标识线程ID的线程号只能通过系统调用syscall(SYS_gettid)获取。

背景:ps -ef|grep tty,出现很多tttyv进程,而有什么用呢?和Linux的不大一样,但又有点一样的,最扣只剩下一个ttyv0   "/usr/libexec/getty Pc"     xterm   on   secure,其余均给关掉,VPS服务器本来内存就少,少一个 进程少点资源占用。
一、发现现象:

二、编辑配置:/etc/ttys文件,vi /etc/ttys ,也就是ttyv0外的,tty1-->tty7都是FreeBSD/i386 (pc3.example.org) (ttyv0),也就是默认就是ttyv0,而其它虚拟终端,FreeBSD 保留了特別的按鍵組合來切換 console,得用 Alt-F1、 Alt-F2、到 Alt-F8來切換 FreeBSD 的不同 console,对于云主机来讲除开查一些登录不了(启动不了,或运程登录不上去)疑难问题外,没有啥鸟用,但有时可能还真有用。


三、关掉没有用的(云主机,虚拟终端ttv0外基本上没有用)重新启动:
重新读取/etc/ttys来强制init对/etc/ttys文件做一个必要的修改后,你必须发送一个SIGHUP信号给初始化进程来迫使它重新读取配置文件,例如:
# kill -HUP 1
注意:init总是系统运行时的第一个进程,因此它总是PID 1。

如果能够正确设置,所有的线缆都是适当的,终端将可以启用了,然后一个getty进程将在每个终端运行,你将在你的终端上看到登陆命令行。
对于终端,init会在每个配置串口上为每个拨入连接产生一个getty进程。例如,如果一个modem被附带在/dev/ttyv1中,用命令ps ax可以显示下面这些:
#ps ax|grep ttyv
2929 v0  Is+       0:00.00 /usr/libexec/getty Pc ttyv0
2930 v1  Is+       0:00.00 /usr/libexec/getty Pc ttyv1
2931 v2  Is+       0:00.00 /usr/libexec/getty Pc ttyv2
2932 v3  Is+       0:00.00 /usr/libexec/getty Pc ttyv3
2933 v4  Is+       0:00.00 /usr/libexec/getty Pc ttyv4
2934 v5  Is+       0:00.00 /usr/libexec/getty Pc ttyv5
2935 v6  Is+       0:00.00 /usr/libexec/getty Pc ttyv6
2936 v7  Is+       0:00.00 /usr/libexec/getty Pc ttyv7

实践如下,留下两个ttyv0,ttyv1,其余都off掉:
(1)ttyv2到ttyv7全部off掉,修改/etc/ttys:


(2)#kill -HUP 1  ,发送一个SIGHUP信号给初始化进程来迫使它重新读取/etc/ttys配置文件。

(3)再看就只有俩了:
#ps -ef|grep tty
2929 v0  Is+  0:00.00 TERM=xterm /usr/libexec/getty Pc ttyv0
2930 v1  Is+  0:00.00 TERM=xterm /usr/libexec/getty Pc ttyv1
四、学习资料来自:ftp://ftp.uwc.ac.za/FOSS/freebsdcvs/www/data/doc/zh_TW/books/handbook/consoles.html
阅读全文
背景:Zabbix的图形里有一项CPU jumps,里面有两条曲线, Context switches per second Interrupts per second。
前言:


阅读全文
用Cshell:
echo $shell
/bin/csh

添加PATH:
vi ~/.cshrc  


注意,$PATH放在最后面,否则会报错,Bad : modifier in $ '/'.  ,Linux不存在这个问题:
setenv PATH $PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/mysql/bin
Welcome to jackxiang's Compute Service !
Bad : modifier in $ '/'.

参考:https://stackoverflow.com/questions/27021663/changing-the-path-variable-on-freebsd
这个没有试过:http://shanchao7932297.blog.163.com/blog/static/136362420109935248893/
linux:
xiangdong登陆
ls /root
权限不够,运行:
sudo !!

列出root家目录内容。


记录命令行会话:
script命令,保存到typescript:script文件,输入一堆后,在输入exit,也就会保存到文件里面去。
linux:
xiangdong登陆
ls /root
权限不够,运行:
sudo !!

列出root家目录内容。


记录命令行会话:
script命令,保存到typescript:script文件,输入一堆后,在输入exit,也就会保存到文件里面去。
总结:本质上是因为PHP的应用程序Owncloud他自己的设置引起了PHP的应用日志时间少了8小时,而PHP的设置 是没有毛病的,如下:
./lib/base.php:         date_default_timezone_set('UTC');  ##修改为:date_default_timezone_set('Etc/GMT-8');
=================================================================================

零、系统时间正确:
date
Sun Feb 11 11:30:16 CST 2018
UTC----全球标准时间指的是由世界时间标准设定的时间。原先也被称为格林威治标准时间或者 GMT
CST----CMOS时间,即本机的时间!

PHP.ini里也配置了:date.timezone = Asia/Shanghai:
在php.ini中设置date.timezone的值为PRC,设置好以后的为:date.timezone=PRC或者date.timezone = Asia/Shanghai,同时取消这一行代码的注释,即去掉前面的分号就可以了。
/usr/local/php/etc/php-fpm.conf里,同样两个日志时间不对:
一、应用错误日志少了8小时:
php-fpm.conf
php_admin_value[error_log] = /data/logs/php/php-www-error.log
/data/logs/php/php-www-error.log
[11-Feb-2018 02:58:53 UTC] PHP Fatal error:  Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60

二、这个php-fpm-error日志和系统时间保持一致:
[global]
error_log = /data/logs/php/php-fpm-error.log
这个是对的:
/data/logs/php/php-fpm-error.log <==
[11-Feb-2018 10:58:37] WARNING: [pool www] server reached pm.max_children setting (6), consider raising it


刚开始认为是FreeBSD的时区问题,但实际上不是它的问题,如下:
FreeBSD 11.1 PHP日志出现:
[11-Feb-2018 03:06:39 UTC] PHP Fatal error:  Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60
系统时间:date
Sun Feb 11 11:18:57 CST 2018
因为刚安装系统是使用UTC时间,所以安装系统后,需要设置回上海时区!操作需要root权限!
#adjkerntz -a                                         调节COMS时间
#date                                                
时间相差8小时,
可能是一个Bug:https://bugs.php.net/bug.php?id=60723 ,但是是 很多年前了,我这都PHP 5.6.33 (cli) (built: Feb 11 2018 10:42:42) ,不存在,后来也证明是Owncloud代码的问题。
http://bbs.csdn.net/topics/390091176里说:php_errors.log (/data/logs/php/php-www-error.log)人家打的是gmtime,你系统时间是localtime,差8小时是正确的,你得想办法配置php_errors.log输出的是localtime就和系统时间一致了,懂吗。


原来是Owncloud是老外做的,设置的date_default_timezone_set可能不一样导致:
#grep -r "date_default_timezone_set" ./
./3rdparty/sabre/vobject/lib/TimeZoneUtil.php:     * (as configured using date_default_timezone_set, or the date.timezone ini
./3rdparty/mcnetic/zipstreamer/src/ZipStreamer.php:    date_default_timezone_set('UTC');
./3rdparty/mcnetic/zipstreamer/src/ZipStreamer.php:    date_default_timezone_set($oldTZ);
./apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php:date_default_timezone_set('UTC');
./apps/files_texteditor/js/vendor/ace/src-noconflict/mode-php.js:        'date_create_from_format|date_date_set|date_default_timezone_get|date_default_timezone_set|date_diff|date_format|date_get_last_errors|' +
./lib/base.php:         date_default_timezone_set('UTC');  ##修改为:date_default_timezone_set('Etc/GMT-8');


成功修复:

手动修改后就OK了,就是PHP代码上作了修改引起的!!!

[11-Feb-2018 11:44:32 Etc/GMT-8] PHP Fatal error:  Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60



灵感来源,下面代码的日志时间正确,date_default_timezone_set('Etc/GMT-8');    //设置时区,这块有关系,于是查Owncloud是否一样?果然不一样,修改了再测试就发现Owncloud对了:
error.class.php


a.php


产生错误时间正确:
[11-Feb-2018 11:39:08 Asia/Shanghai] 2018-02-11 11:39:08 运行时提示(E_NOTICE) Undefined variable: _SESSION /data/www/comm.jackxiang.com/a.php 5
[11-Feb-2018 11:41:59 Asia/Shanghai] PHP Notice:  Undefined index: aaaaadfa in /data/www/comm.jackxiang.com/a.php on line 4
[11-Feb-2018 11:41:59 Asia/Shanghai] PHP Notice:  Undefined variable: _SESSION in /data/www/comm.jackxiang.com/a.php on line 5
[11-Feb-2018 11:41:59 Asia/Shanghai] 2018-02-11 11:41:59 运行时提示(E_NOTICE) Undefined variable: _SESSION /data/www/comm.jackxiang.com/a.php 5

关于这个date_default_timezone_set的一些时间值列表:来自@https://zhidao.baidu.com/question/383369268.html
date_default_timezone_set("Etc/GMT").:是格林威治标准时间,得到的时间和默认时区是一样的
ate_default_timezone_set("Etc/GMT+8");比林威治标准时间慢8小时,
date_default_timezone_set("Etc/GMT-8");东八区,我们比那快8小时所以减8
或者使用:date_default_timezone_set('PRC')设置中国时区


最后,更多关于FreeBSD的时间设置知识:
---------------------------------------------[FreeBSD] 修改系統時間 UTC->CST------------------------------------------------------------
剛安裝好系統是屬於格林時間,所以去設定一下如何弄回去内地 GMT+8 的時間
有2種方式~一個用圖形介面:
1、#tzsetup
是一個不錯的 timezone 設定工具 , 進去之後選擇 5.Asia -> ShangHai
2、另一個方法是:
#cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime
#adjkerntz -a
#date
#Sat Jun 23 10:50:40 CST 200
ps:(adjkerntz = adjust kernal timezone)


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/1808/showart_492283.html
来自:https://www.west.cn/info/html/caozuoxitong/FreeBSD/20090513/132105.html


最近手上弄了台FreeBSD系统的VPS,因为系统无法更换,所以就只能用这么用着了,第一次配置的时候记得配置了时区,可是仍旧显示不正确。这样子看系统日志的时候就不是太方便,因为时间老是不对,虽然这台服务器打算是专门做SSH代×理滴,需要滴联系奶牛哈~~~点此联系

下面说说设置,首先要进入一个root shell

#sysinstall

依次进入 configure→Time Zone→UTC = no→ Asia → China→ Beijing,Guangdong,Shanghai etc.

Does the abbreviation `CST’ look reasonable? = OK
提示选择yes,然后退出sysinstall就可以了。

查看日期的命令是data

同步时间的命令是 ntpdate nist1.symmetricom.com

参考:http://www.nenew.net/freebsd-time-zone-setting.html
https://www.west.cn/info/html/caozuoxitong/FreeBSD/20090513/132105.html
mac下想查看十六进制文件,发现winhex没有mac版本(http://www.haote.com/xz/594902.html),但是搜到了 Hex Fiend,也非常棒,哈哈哈。
轻量级,免费,perfect~
下载地址:http://ridiculousfish.com/hexfiend/

Linux vim 查看16进制之:%!xxd
00000c0: 4163 4371 4553 532d 2d0d 0a              AcCqESS--..

想得到16进制和ascii码对应的显示结果,可以添加 -C参数



xxd查看文件编码:
xxd gbk.php
0000000: 3c3f 7068 700a 2020 7661 725f 6475 6d70  <?php.  var_dump
0000010: 2862 696e 3268 6578 2822 b6ab 2229 293b  (bin2hex(".."));
0000020: 0a                                       .


1. 在 vi 或 vim 的命令状态下

:%!xxd              ——将当前文本转换为16进制格式。

:%!xxd -r           ——将当前文件转换回文本格式。



2. od - dump files in octal and other formats
  顾名思义是查看八进制,可以通过指定参数为查看十六进制
  -A 指定左边侧栏显示的地址基数,默认为八进制
  -t 指定输出单元的进制格式和字节数
  -x = -t x2 输出单元为双字节(注意:每单元内排列顺序从左到右为 [高字节|低字节])

Linux指令:od

示例用法:od -c hello

Linux指令:od

od命令
用户通常使用od命令查看特殊格式的文件内容。通过指定该命令的不同选项可以以十进制、八进制、十六进制和ASCII码来显示文件。

语法:od [选项] 文件…
命令中各选项的含义:
- A 指定地址基数,包括:
d 十进制
o 八进制(系统默认值)
x 十六进制
n 不打印位移值
- t 指定数据的显示格式,主要的参数有:
c ASCII字符或反斜杠序列
来自:http://blog.csdn.net/dumgeewang/article/details/7778143
          http://blog.csdn.net/chenglian_999/article/details/4672177
=========================================

主要用来查看下换行符号:
#od -c S.txt
0000000   1   1   1   1   *   1   +   2   2   2   +   5   *   1   1   +
0000020   8   *   7   7  \n  \n
0000026

#od -c S.txt
0000000   1   1   1   1   *   1   +   2   2   2   +   5   *   1   1   +
0000020   8   *   7   7  \n
0000025


===============Q:=========================
cat S.txt
11+2

od -c S.txt
0000000    1   1   +   2                                                
0000004
-------------------------------------------------------------------------------
bc没有换行,cat filename |bc 会提示:
cat S.txt|bc
bc: stdin:1: syntax error: unexpected EOF

也就是说,还得有一个结尾换行符号。
背景:想到逗号替换为真正的换行,用这个\n不好使,怎么办?一查换行是\r,于是:



学习摘自:VIM如何将空格替换为换行,比如有时需要把很长的一行按空格分为多行,这时就可以用如下命令实现:
:%s/ +/\r/gc

参数解释:
%s :在整个文件范围查找替换
/ : 分隔符
+ :匹配空格,其中“ ”表示空格,+表示重复1次或多次,加在一起表示一个或多个空格。
\r :换行符
g :全局替换
c :替换前确认


来自:http://www.blogdaren.com/m/?post=128
https://github.com/play175/exbuffer.c/blob/master/mingw.makefile 内容:


-finput-charset 指定源文件的编码(若不指定,默认是UTF-8)
-fexec-charset 指定多字节字符串(const char*)常量在编译后的程序里保存的编码集(若不指定,默认是UTF-8)

摘自 :http://blog.csdn.net/qq_28234213/article/details/73277748


exbuffer.c——纯C写的TCP中的粘包、分包问题的解决方案里的mingw.makefile :
https://yoyo.play175.com/p/exbuffer_c.html
看了很多tcp文章都看不懂,这篇文章好像懂了,有空试试,说的是不是真的。

和三次握手相关的TCP报文中的重要标志位

昨天的文章中,结合Wireshark抓包和大家讨论了三次握手的相关知识点,评论中有些读者对序号,确认序号,以及SYN&ACK等标志位还有一些疑问,这里简单再说一下我的理解。其中ACK的32位值在Wireshark抓包时显示的是相对的值,可设置为显示真实值:http://mini.eastday.com/a/180131063435528.html

首先,由TCP协议报文的格式可知,在报文中我们主要关注与《32位序列号》,《32位确认序号》,和SYN和ACK标志位。因为这四个要素和三次握手紧密相关。阅读全文
大多原因是删除的文件被系统进程打开,那么文件实际上并没有被删除,因此空间没有被释放。
三次发现类似文件:
lsof -n /sec_syslog/
COMMAND    PID USER   FD   TYPE DEVICE     SIZE/OFF    NODE NAME
rsyslogd  1228 root   11w   REG 253,17    701955294 9437186 /sec_syslog/2024-05-05/10.71.59.14.log (deleted)
rsyslogd  1228 root   26w   REG 253,17        21333 9437187 /sec_syslog/2024-05-05/127.0.0.1.log (deleted)
rsyslogd  1228 root   27w   REG 253,17  40433209822 6553602 /sec_syslog/2024-05-06/10.71.59.14.log (deleted)
猜测是因为sec_syslog导致的,以下得到验证:
lsof  -nPp 1228|grep sec_syslog
rsyslogd 1228 root   11w      REG             253,17    701955294   9437186 /sec_syslog/2024-05-05/10.71.59.14.log (deleted)
rsyslogd 1228 root   26w      REG             253,17        21333   9437187 /sec_syslog/2024-05-05/127.0.0.1.log (deleted)
rsyslogd 1228 root   27w      REG             253,17  40433209822   6553602 /sec_syslog/2024-05-06/10.71.59.14.log (deleted)
rsyslogd 1228 root   28w      REG             253,17      4649024   6553603 /sec_syslog/2024-05-06/127.0.0.1.log (deleted)
rsyslogd 1228 root   29w      REG             253,17      3681387   2883586 /sec_syslog/2024-05-07/127.0.0.1.log (deleted)
rsyslogd 1228 root   30w      REG             253,17 119666961091   2883587 /sec_syslog/2024-05-07/10.71.59.14.log (deleted)
rsyslogd 1228 root   31w      REG             253,17      5869568   6946818 /sec_syslog/2024-05-08/127.0.0.1.log (deleted)
rsyslogd 1228 root   32w      REG             253,17  50329927680   6946819 /sec_syslog/2024-05-08/10.71.59.14.log (deleted)
重启后,也就好了:
df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb1       197G   78M  187G   1% /sec_syslog


二次发现类似问题:还得靠lsof -n / |grep deleted  ,操作如下:
删了大文件,但是这个文件没有释放,ls -n / |grep deleted 反查到
lsof -n / |grep deleted
baserepor  3827      root    2w   REG  253,1           0 2492090 /tmp/xuoasefasd.err (deleted)
tshark    47796      root    5r   REG  253,1 14106508896 2492042 /tmp/wireshark_pcapng_eth0_20201015103006_KWTDIm (deleted)
dumpcap   47802      root    4u   REG  253,1 14106508896 2492042 /tmp/wireshark_pcapng_eth0_20201015103006_KWTDIm (deleted)

查命令历史:
root_shell_cmd [xiangdong 10.4.12.52] [/tmp] 1056  [2020-10-15 11:52:14] cd wireshark_pcapng_eth0_20201015103006_KWTDIm
root_shell_cmd [xiangdong 10.4.12.52] [/tmp] 1057  [2020-10-15 11:52:17] tail -f wireshark_pcapng_eth0_20201015103006_KWTDIm
root_shell_cmd [xiangdong 10.4.12.52] [/tmp] 1058  [2020-10-15 11:52:21] ls
root_shell_cmd [xiangdong 10.4.12.52] [/tmp] 1059  [2020-10-15 11:52:24] rm -rf wireshark_pcapng_eth0_20201015103006_KWTDIm

再次确认删了,但是磁盘空间还在:
ls -lart /tmp/wireshark_pcapng_eth0_20201015103006_KWTDIm
ls: cannot access /tmp/wireshark_pcapng_eth0_20201015103006_KWTDIm: No such file or directory

由于是tahshrk,估计tcpdump是它调用起来的,应该也是,查看进程名:
cat /proc/47796/status |grep Name
Name:   tshark
ps -eo"pid,ppid,gid,sid,tty,cmd" --forest|less
1238     1     0  1238 ?        /usr/sbin/sshd -D
42045  1238     0 42045 ?         \_ sshd: xiangdong [priv]
42047 42045  1040 42045 ?         |   \_ sshd: xiangdong@pts/0,pts/1,pts/2,pts/3
47537 42047  1040 47537 pts/1     |       \_ -bash
47585 47537  1040 47537 pts/1     |       |   \_ sudo su -
47586 47585     0 47537 pts/1     |       |       \_ su -
47587 47586     0 47537 pts/1     |       |           \_ -bash
47628 47587     0 47537 pts/1     |       |               \_ sudo su -
47629 47628     0 47537 pts/1     |       |                   \_ su -
47630 47629     0 47537 pts/1     |       |                       \_ -bash
47796 47630     0 47537 pts/1     |       |                           \_ tshark -n -t a -R http.request -T fields -e frame.time -e ip.src -e http.host -e http.request.method -e http.request.uri
47802 47796     0 47537 pts/1     |       |                               \_ /sbin/dumpcap -n -i eth0 -Z none

果然:
root     47796 47630  2 10:30 pts/1    00:04:51  |       |                           \_ tshark -n -t a -R http.request -T fields -e frame.time -e ip.src -e http.host -e http.request.method -e http.request.uri
root     47802 47796  0 10:30 pts/1    00:00:36  |       |                               \_ /sbin/dumpcap -n -i eth0 -Z none

杀了它就好了,磁盘就释放了:
df -h
/dev/vda1        40G   37G  583M  99% /
变为:
pkill tshark
df -h
/dev/vda1        40G   24G   14G  64% /

告诉我们要记得退出tshark,别让它后台运行,删文件前用 lsof wireshark_pcapng_eth0_20201015103006_KWTDIm 看这个tshak进程还在不在。
来自:https://www.cnblogs.com/zhangrongfei/p/12463466.html

经过lsof直接看文件谁打开了:#lsof /var/log/messages
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF      NODE NAME
rsyslogd 1994 root    6w   REG  253,0    39892 101327940 /var/log/messages

背景:机器长时间运行往往磁盘空间满了,但是删除了还是占用很大空间和没删除几乎一样,怎么办?
运维监控系统发来通知,报告一台服务器空间满了,登陆服务器查看,根分区确实满了,这里先说一下服务器的一些删除策略,由于 linux 没有回收站功能,所以线上服务器上所有要删除的文件都会先移到系统 / tmp 目录下,然后定期清除 / tmp 目录下的数据。这个策略本身没有什么问题,但是通过检查发现这台服务器的系统分区中并没有单独划分 / tmp 分区,这样 / tmp 下的数据其实占用根分区的空间,既然找到了问题,那么删除 / tmp 目录下一些占用空间较大的数据文件即可。

发现真出现了,一个队列进程把磁盘写满后,即使杀死PHP队列进程和对应的大文件后df -h的/ 100%占满,经lsof |grep "Remote.log"发现是Filebeat:
实践解决如下,确定杀光了:
ps aux |grep  Daemon |awk '{print $2}' |xargs kill -9
kill 10379: No such process
空间还是占用100%,用 lsof查看,这个命令还可以用来看端口对应的程序,如:
/usr/sbin/lsof -i tcp:5902
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
Xvnc    24560 root    9u  IPv4 763173      0t0  TCP *:5902 (LISTEN)
Xvnc    24560 root   10u  IPv6 763174      0t0  TCP *:5902 (LISTEN)

lsof -i :80
COMMAND   PID USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
nginx   41167 root   18u  IPv4 249906712      0t0  TCP *:http (LISTEN)

lsof |grep "Remote.log" 发现是filebeat :

重启一下Filebeat下吧:
/etc/init.d/filebeat restart
Stopping filebeat:
Config OK
Stopping filebeat:                                         [  OK  ]
2018/03/22 08:29:07.965771 config.go:86: INFO Additional configs loaded from: /etc/filebeat/conf.d/sec.yml
Config OK                                                   [  OK  ]
再看这个文件还在,是新生成的,但是空间就变正常了。AddTime:2018-03-22
                                                          
=============================================================================
# du -sh /tmp/* | sort -nr |head -3
通过命令发现在 / tmp 目录下有个 66G 大小的文件 access_log,这个文件应该是 apache 产生的访问日志文件,从日志大小来看,应该是很久没有清理的 apache 日志文件了,基本判定是这个文件导致的根空间爆满,在确认此文件可以删除后,执行如下删除命令,
# rm /tmp/access_Iog
# df -h

从输出来看,根分区空间仍然没有释放,这是怎么回事
一般来说不会出现删除文件后空间不释放的情况,但是也存在例外,比如文件进程锁定,或者有进程一直在向这个文件写数据,要理解这个问题,就需要知道 linux 下文件的存储机制和存储结构。

一个文件在文件系统中存放分为两个部分:数据部分和指针部分,指针位于文件系统的 meta-data 中,在将数据删除后,这个指针就从 meta-data 中清除了,而数据部分存储在磁盘中。在将数据对应的指针从 meta-data 中清除后,文件数据部分占用的空间就可以被覆盖并写入新的内容,之所以出现删除 access_log 文件后,空间还没有释放,就是因为 httpd 进程还在一直向这个文件写入内容,导致虽然删除了 access_Ilog 文件,但是由于进程锁定,文件对应的指针部分并未从 meta-data 中清除,而由于指针并未删除,系统内核就认为文件并未被删除,因此通过 df 命令查询空间并未释放。

问题排查:
既然有了解决思路,那么接下来看看是否有进程一直在向 access_log 文件中写入数据,这里需要用到 linux 下的 losf 命令,通过这个命令可以获取一个仍然被应用程序占用的已删除文件列表

# lsof | grep delete
从输出可以看出,/tmp/access_log 文件被进程 httpd 锁定,而 httpd 进程还一直向这个文件写入日志数据,最后一列的‘deleted’状态说明这个日志文件已经被删除,但是由于进程还在一直向此文件写入数据,因此空间并未释放。

解决问题:
到这里问题就基本排查清楚了,解决这一类问题的方法有很多,最简单的方法就是关闭或者重启 httpd 进程,当然重启操作系统也可以。不过这些并不是最好的办法,对待这种进程不停对文件写日志的操作,要释放文件占用的磁盘空间,最好的方法是在线清空这个文件,具体可以通过如下命令完成:
# echo “”>/tmp/access_log

通过这种方法,磁盘空间不但可以马上释放,也可以保障进城继续向文件写入日志,这种方法经常用于在线清理 apache /tomcat/nginx 等 web 服务产生的日志文件。



摘自:http://mp.weixin.qq.com/s/AJtnz_CE3pmhoaMHm6HNXA
背景:Zabbix报警进程数太多报警Too many processes on servername ...。发现是Sendmail进程数太多。
ps -ef|grep sendmail|wc -l
569
-bash: /data/logs/.syshistory/bash_history.log: Read-only file system
/usr/sbin/postdrop -r
/usr/sbin/sendmail -FCronDaemon -i -odi -oem -oi -t -f root
[aio/21]
[kblockd/18]
[kondemand/0]
[kondemand/1]
[kondemand/N]


执行top的时候发现当前用户下面有很多sendmail的进程,如下图所示,发件人是crondaemon,怀疑是和定时任务有关,查看当前用户的定时任务发现有一个每分钟运行一次的定时任务,但是定时脚本是没有调用sendmail了,ps -ef | grep sendmail | wc -l 统计发现sendmail的进程数据基本上就是从服务器出故障到当前时间的分钟数。


然道是crontab每次执行都会调用sendmail发邮件吗?man 5 crontab查看帮助手册的时候发现这个一段话:
In  addition  to  LOGNAME,  HOME,  and SHELL, cron(8) will look at MAILTO if it has any reason to send mail as a result of running commands in "this" crontab.  If MAILTO is defined (and non-empty), mail is sent to the user so named.  If MAILTO is defined but empty (MAILTO=""), no mail will be sent.  Otherwise mail is sent to the owner of the crontab.  This option is useful if you decide on /bin/mail instead of /usr/lib/sendmail as your mailer when you install  cron  -- /bin/mail doesnt do aliasing, and UUCP usually doesnt read its mail. If MAILFROM is defined (and non-empty), it will be used as the envelope sender address, otherwise, ‘‘root’’ will be used.


查看crontab的配置文件:
cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

可以看到MAILTO这一行不为空,如果不想让它发邮件的话可以按照手册上面说的把MAILTO这一行删掉或者改为MAILTO=""

From:http://blog.51cto.com/chenql/1878182
/data/codesdev/testdemo/c++/map/stl_map.cpp


make stl_map
g++     stl_map.cpp   -o stl_map

./stl_map
Bill, A senior heigh school student.
Join, A senior heigh school student.
Marry, A senior heigh school teacher.


/data/codesdev/testdemo/c++/map/stl_map_find.cpp

make stl_map_find
g++     stl_map_find.cpp   -o stl_map_find
./stl_map_find
elements in mymap:
a => 50
c => 150
d => 200
b => 0
e => 0


修改那个位置判断为:
[codes=php]
     it = mymap.find('d');
     if (it != mymap.end())    #if (iter == g_map_fd_TcpNLMsg.end())假如到最扣一个依然没有找到的意思。一般就直接返回。
         mymap.erase (it);
[/php]
这样的结果:
./stl_map_find        
elements in mymap:
a => 50
c => 150
d => 0
b => 100
e => 0


来自:http://blog.csdn.net/derkampf/article/details/71155055
常见的网络字节转换函数有:
htons():host to network short,将short类型数据从主机字节序转换为网络字节序。
ntohs():network to host short,将short类型数据从网络字节序转换为主机字节序。
htonl():host to network long,将long类型数据从主机字节序转换为网络字节序。
ntohl():network to host long,将long类型数据从网络字节序转换为主机字节序。

通常,以s为后缀的函数中,s代表2个字节short,因此用于端口号转换;以l为后缀的函数中,l代表4个字节的long,因此用于IP地址转换。
————————————————————————————————————————————————————————————————
cat hto.c


make hto
cc     hto.c   -o hto

#./hto
Host ordered port: 0x1234
Network ordered port: 0x3412
Host ordered address: 0x12345678
Network ordered address: 0x78563412


cat inetaddr.c



make inetaddr  
cc     inetaddr.c   -o inetaddr

./inetaddr
Network ordered integer addr: 0x101a8c0
Network ordered integer addr: 0xb01a8c0

From:http://c.biancheng.net/cpp/html/3047.html
vim查看插件:scriptnames
:scriptnames

安装插件的主法,且把要安装插件的配置文件和~/.vimrc文件区分开来了,链接如下:
https://blog.csdn.net/lu_embedded/article/details/76732965

Vim 自 7.0 开始支持 tab 页了,这就像很多数文本编辑器那样方便在多文件中切换,而不是只能使用 Buffer 暗地里来回切。默认时标签上显示 tab 序号加上当前打开的文件名。
Vim 中关于 Tab 的操作命令如下:
vim -p file1 file2 file3....   在多标签中打开多个文件
:tabe[dit] 或  :tabnew          在当前标签后打开新的标签
:tabn[ext] 或 gt         切换到下一个 tab
:tabp[revious] 或 gT   切换到上一个 tab
:tabn [N]    切换到第 N 个 tab
:tabfir[st]   切换到第 1 个 tab
:tabl[ast]    切换到最后一个 tab
:tabs      列出所有的 tab
:tabc[lose]  关闭当前 tab,    :q 命令也能关闭闭掉当前 tab
:tabo[nly]   关闭所有其它 tab

Vim杂记:Sublime的配色方案,出现在SecureCRT里的Vim一闪一闪的,失败,取消此配色:
http://www.cnblogs.com/fsjohnhuang/p/3911611.html

当Vim 打开了很多buffer 和tab 的时候,想要在不同窗口之间跳转,会比较麻烦,刚给SpaceVim 开发了一款简单的插件,就是在左侧列出所有tab:
https://github.com/SpaceVim/SpaceVim

git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle
编辑你当前用户下的.vimrc

[xiangdong@localhost ~]$ vim ~/.vimrc
输入Vundle对应的配置

"======================== Vundle 配置 ============================  
"安装方法用这个:git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle
set nocompatible
filetype off
set rtp+=~/.vim/bundle/vundle/ "载入特定目录插件
call vundle#rc()
=============================================================

cat /home/xiangdong/.vimrc

在Vim中运行 :BundleInstall 等待安装完成。
:BundleInstall


ctrl + j/k  # 进行上下选择
ctrl + x    # 在当前窗口水平分屏打开文件
ctrl + v    # 同上, 垂直分屏
ctrl + t    # 在tab中打开
From:https://www.jianshu.com/p/c67e60abaa45

vim中的杀手级插件: vundle: http://zuyunfei.com/2013/04/12/killer-plugin-of-vim-vundle/
安装插件
打开一个vim, 运行:BundleInstall

或者在命令行运行 vim +BundleInstall +qall

安装完成后插件就能用了

####其它常用命令:

更新插件:BundleUpdate
清除不再使用的插件:BundleClean,
列出所有插件:BundleList
查找插件:BundleSearch
BundleUpdate报错:[Git] Unable to find remote helper for ‘https’
可能是在安裝 git 時因為缺少 libcurl 套件所導致

但是環境沒有 libcurl 時一樣可以安裝,只是會不能走 HTTPS 通道而已
若要修復這個問題,只需安裝 libcurl 後重新編譯安裝 git 就好:
# 系統為Ubuntu/Debain時,執行以下指令
apt-get install -y libcurl4-openssl-dev

# 系統為CentOS/RedHat/Fedora時,執行以下指令
yum install -y libcurl-devel.x86_64
From:https://caloskao.org/git-unable-to-find-remote-helper-for-https/

# 回到 git 原始碼目錄重新編譯並安裝 git
cd git-2.7.4
./configure
make prefix=/usr/local all
make prefix=/usr/local install
git --version

:BundleUpdate ,出现:Cannot make changes, 'modifiable' is off
:set modifiable
or
:set ma
来自vim 修改时提示 E21: Cannot make changes, 'Modifiable' is off:https://www.jianshu.com/p/2a511ebcdd9a
实践OK如下:
vi ./bundle/vundle/autoload/vundle/scripts.vim
166   set modifiable=on  
报语法错:后又修改为恢复原来后,又莫名其妙的好了:
164   " make buffer modifiable
165   " to append without errors
166   set modifiable  



结论:VIM有其和UI编辑器的局限,也有其灵活,Sublime有其存在价值,想学不一定能学好。多了快捷键还会冲突等得自己思考布局,是有 灵活性,而较为优秀的UI编辑器,早就精心设置好了,你只需要会开就成,所以,我只选择了vim-multiple-cursors,发现其它插件在vim-multiple-cursors的ctrl+n选中单词向前,Ctrl+p后通,Ctrl+x将选中变为不选中再会跳向下一个,选中完成后,可以使用大写i光标之前插入,大写c删除选中批量修改等vim编辑操作进入insert模式,开始修改文本.,好像出现了覆盖。不想深入,先用着,就这样吧:

步骤一二就行,简单常用批量替换插件即可。

通过Vim+少量插件配置一个高效简洁的IDE:  https://www.cnblogs.com/javaminer/p/3842689.html  
实践,先安装插件管理 再装vim-multiple-cursors这款插件:
一)vim插件管理器:Vundle的介绍及安装:
vim中的杀手级插件: http://zuyunfei.com/2013/04/12/killer-plugin-of-vim-vundle/  ##选中后, 可以进行增删替换a/c/x等,相关常用细节参考:http://foocoder.com/2014/04/09/mei-ri-vimcha-jian-vim-multiple-cursors/ ,移动光标到下一个单词的结尾,用命令”e“,里面的ctrl+e在SecureCRT里面并不能到行尾,用箭头键慢慢移动吧。
这个得装:
$git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim
Initialized empty Git repository in /home/xiangdong/.vim/bundle/Vundle.vim/.git/
remote: Counting objects: 3132, done.
Receiving objects:  22% (690/3132), 124.01 KiB | 38 KiB/s  
vim +BundleInstall + vundle  

二)http://www.wklken.me/posts/2015/06/07/vim-plugin-multiplecursors.html
PluginInstall  vim-multiple-cursors
:Plugin 'terryma/vim-multiple-cursors'
这个:
:PlugInstall multiple-cursors

从Github进行安装:
Plugin 'terryma/vim-multiple-cursors'
vim +BundleInstall + vim-multiple-cursors
vim +BundleInstall + ctrlp-funky       #https://www.cnblogs.com/javaminer/p/3842689.html
vim +BundleInstall + taglist.vim
vim +BundleInstall + nerdtree
链接:http://zuyunfei.com/2013/04/12/killer-plugin-of-vim-vundle/


三)Bundle 'ctrlpvim/ctrlp.vim'  #这个不是??

Bundle 'kien/ctrlp.vim'
github:https://github.com/kien/ctrlp.vim这是一个超赞的插件,如果使用过sublime-text2,那么肯定很熟悉ctrlp。它可以快速的帮助我们找到项目中的文件。
https://www.jianshu.com/p/SRsmZW


================================================
一)推荐vim-multiple-cursors这款插件,是模仿sublime的多光标模式,查找规则就是vim默认的单词匹配(就是你按*时查找单词的规则),像这样:大部分时候还是可以用来做rename refactor的。不过正如楼上所说,做项目还是老实用IDE吧 :)
From:https://zhuanlan.zhihu.com/p/23262156 ,在命令行模式下用批量替换啊。:%s/item/item /gc 加c是让你一个个确认。
插件地址:https://github.com/terryma/vim-multiple-cursors

二)ctrlp.vim 这个插件是模仿Sublime Text 的ctrl + p功能,在工程中快速定位某个文件。
三) 'ZenCoding.vim'. " 模仿sublime text 的ctrl + shift + f 在工程中全局查找某字符. " 需先安装ack (这个有Shell下的Linux命令Grep,用了插件快捷键没有了)


Ctrl-P在其他编辑器里已经是默认的全局搜索键了,vim 也有ctrlp(https://github.com/ctrlpvim/ctrlp.vim)插件,它可以搜索文件路径上的文件名,还有最近文件等各种快捷打开。看起来似乎挺好的,直到fzf.vim(https://vimawesome.com/plugin/fzf-vim)的出现。fzf的搜索速度更快,而且异步,不会在初始化搜索的时候卡死界面响应。

安装好fzf,然后加载 fzf.vim 插件,将ctrl-p 键位映射成 :Files<CR>,就可以体验到高速搜索,中间根本不用等界面响应,等关键词输入,结果就出来了。配合 ag 可以屏蔽掉.gitignore 内的文件。

搜索除了文件快速打开,还有全局行内搜索,之前vimgrep 一直是一个比较常用的命令,然而体验不太好,需要指定搜索内容和搜索范围,还要输一些命令,而且略慢。那么ag(https://github.com/ggreer/the_silver_searcher)一定是目前最好的选择。不管其他因素,进到项目主页,一看是 c 写的基本上就已经稳了。实际上它也确实是目前为止最快的行内搜索。使用的话,需要先安装命令行ag(https://github.com/ggreer/the_silver_searcher),然后安装ack.vim(https://vimawesome.com/plugin/ack-vim),注意不要用ag.vim 它已经不被支持了。

不过有个问题,fzf也内置了对 ack 的支持,只是比ack.vim 不如,所以需要重新映射一个 ack.vim 使用的键位,我个人用了 <Leader>f 意为 find。
分页: 11/40 第一页 上页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 下页 最后页 [ 显示模式: 摘要 | 列表 ]