背景:Linux下的硬件有很多,如何看网卡是啥样的,声卡是啥样的有几个USB口及品牌。


该命令作用:将lspci的输出当做输入,从中找出包含Eth的行。在我的Fedora机器上运行结果为

[root@localhost etc]# lspci | grep Eth
00:04.0 Ethernet controller: Silicon Integrated Systems [SiS] SiS900 PCI Fast Ethernet (rev 91)

lspci命令解说:该命令能列出机器中的PCI设备信息,如声卡,显卡,Modem,网卡等信息,主板集成设备的信息也能列出来,lspci读取的是hwdata数据库。

| 管道命令,之前的输出作为之后的输入

grep grep命令后设置指定过滤的字符串,任何没有包括指定字符串的行都不会显示。

来自:http://www.cnblogs.com/xiandedanteng/archive/2013/08/23/3277746.html
前置:Linux多进程和多线程的一次gdb调试实例:https://typecodes.com/cseries/multilprocessthreadgdb.html ,Linux C/C++开发中gdb进行多进程和多线程的调试一直比较麻烦,在CSDN上看到高科的一篇文章《gdb调试多进程和多线程命令》比较有启发,这里就自己重新整理并做了一个GDB多进程/线程的调试实践。
这个表很重要,两个参数一块用:


也可将前面的set添加到~/.gdbinit来打开non-stop模式:


查看相关命令:
set follow-fork-mode child
set detach-on-fork off
info inferiors                    #####显示正在调试的进程
inferior 2
show detach-on-fork #Whether gdb will detach the child of a fork is off.
show follow-fork-mode #Debugger response to a program call of fork or vfork is "child"
info b #查看断点
进程树:
pstree -pul
PS查看自己程序名运行的多进程:
ps -f -C multepoolser

break  if
要想设置一个条件断点,可以利用break if命令,如下所示:
[cpp] view plain copy
(gdb) break line-or-function if expr  
(gdb) break 46 if testsize==100  
clean number
清除原文件中某一代码行上的所有断点
注:number 为原文件的某个代码行的行号


断点的管理
1. 显示当前gdb的断点信息: info break
2. delete 删除指定的某个断点: delete breakpoint

单步执行
continue      继续运行程序直到下一个断点(类似于VS里的F5)
next            逐过程步进,不会进入子函数(类似VS里的F10)  #这个不进入函数里。
setp            逐语句步进,会进入子函数(类似VS里的F11) 的确能进入到函数里面。
until           运行至当前语句块结束  #没弄明白,试了试没找到规律
finish          运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)
next/n 不进入的单步执行 step 进入的单步执行
finish
如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令finish
call name
调用和执行一个函数
(gdb) call gen_and_sork( 1234,1,0 )  
(gdb) call printf(“abcd”)  
$1=4  
finish 结束执行当前函数,显示其返回值(如果有的话)

原文件的搜索 search text
该命令可显示在当前文件中包含text串的下一行。
reverse-search text
该命令可以显示包含text 的前一行。

set variable 给变量赋值
signal 将一个信号发送到正在运行的进程
watch 在程序中设置一个监测点(即数据断点)
whatis 显示变量或函数类型

来自GDB调试精粹:http://blog.csdn.net/lwbeyond/article/details/7839225

GDB打印所有字符串:@ http://blog.csdn.net/shuizhizhiyin/article/details/53227913

如果出现No symbol "header_line" in current context.,你得切换到那个进程里面去,能切换进去的前提是你提前打了断点:
(gdb) p header_line
No symbol "header_line" in current context.
可:info thread 切换到对应的进程,再打印也就有了。


break FileName.cpp:LinuNum thread all:所有线程都在文件FileName.cpp的第LineNum行有断点。
thread apply ID1 ID2 IDN command:多个线程执行gdb命令command。
thread apply all command:所有线程都执行command命令。
set scheduler-locking off|on|step:在调式某一个线程时,其他线程是否执行。off,不锁定任何线程,默认值。on,锁定其他线程,只有当前线程执行。step,在step(单步)时,只有被调试线程运行。
set non-stop on/off:当调式一个线程时,其他线程是否运行。
set pagination on/off:在使用backtrace时,在分页时是否停止。
set target-async on/ff:同步和异步。同步,gdb在输出提示符之前等待程序报告一些线程已经终止的信息。而异步的则是直接返回。
来自:http://blog.csdn.net/helloktt/article/details/73252943
http://www.tolxs.com/?p=302
(gdb)  show detach-on-fork
Whether gdb will detach the child of a fork is off.
(gdb) show follow-fork-mode
Debugger response to a program call of fork or vfork is "child"

出现:
(gdb) n
Cannot execute this command while the selected thread is running.

(gdb) info threads
  Id   Target Id         Frame
  3    Thread 0x7fffece72700 (LWP 27660) "multepoolser" handleEpollRdMessage (threadNum=0) at multepoolser.c:262
* 2    Thread 0x7ffff7fde840 (LWP 21243) "multepoolser" (running)
  1    Thread 0x7ffff7fde840 (LWP 21239) "multepoolser" 0x00007ffff668774c in fork () from /lib64/libc.so.6

root     21239 16286  0 17:22 pts/1    00:00:00 [httpmut: master process] master process
apache   21243 21239  0 17:22 pts/1    00:00:00 [httpmut: worker process] worker process

目前在进程:2,前面有*号,我得到3上面去,怎么弄?
thread 3
(gdb) thread 3
[Switching to thread 3 (Thread 0x7fffece72700 (LWP 27660))]
#0  handleEpollRdMessage (threadNum=0) at multepoolser.c:262
262         printf("handleEpollRdMessage function 's threadNum=%d\n",threadNum);
(gdb) n
handleEpollRdMessage function 's threadNum=0
263         int recvlen=-1,epollRdQueRet=-1;//返回
info threads #此时就在3了吧
(gdb) info threads
  Id   Target Id         Frame
* 3    Thread 0x7fffece72700 (LWP 27660) "multepoolser" handleEpollRdMessage (threadNum=0) at multepoolser.c:263
  2    Thread 0x7ffff7fde840 (LWP 21243) "multepoolser" (running)
  1    Thread 0x7ffff7fde840 (LWP 21239) "multepoolser" 0x00007ffff668774c in fork () from /lib64/libc.so.6

卡这儿了,也就是主进程网络那边没有来Epoll句柄,getepollRdFromQue队列一直是空的,怎么办?
(gdb) p epollRdQueRet
$2 = -1
(gdb) n
455         }
(gdb)
302             epollRdQueRet = getepollRdFromQue(&sockRdQue[threadNum],&epollRd);//只要有生产的fd进来并该线程获取到了,就立即去epoll读队列里抢,一线程一队列,不用锁。
(gdb)
303             if(epollRdQueRet == -1) continue;//没有获取到epollRd,继续获取。
(gdb)
455         }

此时如果有的进程需要运行,怎么办?GDB命令:thread apply 3 1 continue #让线程3继续运行,注意我顾意把主线程1也continue。
thread apply 3 1 2 continue


需要实践,链接如下:
http://blog.sina.com.cn/s/blog_53fab15a0101g88r.html
https://www.cnblogs.com/frankbadpot/archive/2010/06/23/1762916.html
http://blog.csdn.net/wangyin159/article/details/47169267

=============================================================================

背景:当你在做一些多进程调试时,会出现一个问题,那就是子进程往往不太好调试,怎么办?如果子进程一直在while里飞快的运行着怎么办,这篇文章就是教会你进行双gdb调试,以实现了子进程的调试,这儿在没有调试时,其子进程是不断的打印,当然最好在while里加一个sleep,但第二个gdb进入后则会存在第一个gdb的打印变慢了,此时,可以在第二个gdb里打印相关变量,达到对子进程的调试目的,特别注意的是,第二个gdb一定要在那个子进程的行里break(这儿是31行)进行调试,而不是放在其它地方,否则是没法调试到子进程的。第三个是:进程中断点.然后用c(这里要用continue,因为attach的进程已经在运行了,不能用run)。最后,子进程死了父亲进程拉起,crack这块可能是return退出了,自己打印是crack,导致并不是真正的crack了,也就不是coredump了,特别注意这个问题。
     当你在程序中使用fork(),如果用gdb来调试.不管是你在子进程是否设置断点.你都只能在父进程单步调试,而没办法进入到子进程当中进行单步调试.因为gdb的所有处理(查看堆栈,内存,变量值)都是针对当前进程空间.

那么是否就没办法调试多进程程序的子进程代码呢?办法还是有的,一般的标准方法是再打开一个gdb用attach功能来调试子进程gdb attach 功能是不执行被调试程序,而是把gdb“挂”到一个已经运行的进程之上来进行调试,这挂载的动作称为attach.当然也包括挂载子进程。

注意两点:
0.当主gdb进来后进行断点后,子进程尽管断点了,但依然运行(为第二个gdb作暂停准备之用),而当第二个gdb对子进程进行attach后,其主gdb的子进程的打印动作也就暂停(为方便调试,可以在进程启动后,设定sleep一段时间,如30s,其实只要第二个gdb一attach到子进程,子进程就柱塞了。),此时子gdb再进行设置断点,按c运行,按n作next就行。
1.子进程的主gdb点和第二个gdb的break点要同一行?不必要,其主gdb只是起到在第二个gdb单独调该进程时起到暂停其主的子进程的作用罢了。
2.在子进程的gdb里,要用c来继续,(这里要用continue,因为attach的进程已经在运行了,不能用run!(也就是:主进程用r(先运行着,主进程不退出。),子进程用c,继续在原来那个停下来的点继续运行到后,再用n命令,即next一步一步查问题,n(next):显示的是即将运行这一行,也就是还没有运行。)
3.gdb调试epoll时遇到的Interrupted system call:
signal(SIGALRM,timer_handle);
最近写了个多线程数据处理的程序,其中用到sem_wait()在信号量为0的时候挂起程序. 程序全速执行的时候没有任何问题,但gdb单步调试的时候,因执行sem_wait()函数而挂起的线程经常出现Interrupted system call,不能正常执行.
    原因在于,gdb单步调试的时候会在断点处插入一条中断指令,当程序执行到该断点处的时候会发送一个SIGTRAP信号,程序转去执行中断相应,进而gdb让程序停下来进行调试. 对于sem_wait\wait\read等会阻塞的函数在调试时,如果阻塞,都可能会收到调试器发送的信号,而返回非0值.
    为了解决这个问题需要在代码中忽略由于接收调试信号而产生的"错误"返回:


到一篇文章《gdb常用命令及使用gdb调试多进程多线程程序》:http://www.cnblogs.com/33debug/p/7043437.html ,代码编译无法通过,代码调整如下,gdb_pthread.c:



关于GDB无法调试epoll的疑问?
这种交互式的网络程序最好不用gdb来调?
调试网络通讯程序最好别用GDB,epoll你可以用strace,gdb是用来调试 C数据结构逻辑之类的。
打日志是我的首选调试方法,如果程序崩溃就看core 文件,如果死锁就 attach上去,其他的错误我从不用GDB
不是epoll和gdb的问题,而是在gdb下epoll_wait 信号处理和正常运行有差异造成的,应该是这个。
摘自:http://bbs.chinaunix.net/thread-1551201-1-1.html

多进程调试如下所述即可,如下,特别是新的linux内核版本能支持到多进程了,相当好用:
在2.5.60版Linux内核及以后,GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。
follow-fork-mode的用法为:
set follow-fork-mode [parent|child]
parent: fork之后继续调试父进程,子进程不受影响。
child: fork之后调试子进程,父进程不受影响。
因此如果需要调试子进程,在启动gdb后:
(gdb) set follow-fork-mode child

这块可以研究一下,新的内核及新的gdb有新功能很方便使用:
set follow-fork-mode child
//set detach-on-fork on //gdb控制父子进程,不让调试了: Can't attach LWP 24731: Operation not permitted,得打开:ON。
b 146 //main里的子进程行
b 192  //子进程调用的函数原型行
r //执行到子进程断点处
n //子进程单步执行

实践心得:一般情况下多线程的时候,由于是同时运行的,最好设置 set scheduler-locking on 这样的话,只调试当前线程 。
off 不锁定任何线程,也就是所有线程都执行,这是默认值。 on 只有当前被调试程序会执行。
vi bp.list

gdb.sh

(一)这块在调试epoll时,在n单步执行卡后(c执行前先断点),得通过浏览器模拟socket请求才能过得去,否则会一直卡那儿,如下:


这块如果continue后,中间因为断点就一次是没法下次进入的,需要引入gdb判断(if {expression} else end条件判断语句, if 后面所带的表达式为一般的GDB表达式:http://blog.csdn.net/horkychen/article/details/9372039)及观察点,才能更加深入了解,下面是试图没有断点运行起来后实现ctrl+C退出,想继续n的尝试:
(二)再就是对c后一直卡那儿,可以按ctrl+C退出( SIGINT   :来自键盘的中断信号 ( ctrl + c ) .),SIGTERM:kill 命令发出 的信号.,继续n执行:
Program received signal SIGINT, Interrupt.
0x0000003c9a2d3fd3 in __epoll_wait_nocancel () from /lib64/libc.so.6
(gdb) n
Single stepping until exit from function __epoll_wait_nocancel,
which has no line number information.

这块不知怎么回事....需要进一步学习了解。

Process(listenFd); //运行至工作子进程的函数,;b 192进行单步执行。

直接gdb后attach子进程:
#ps -f -C multepoolser
UID        PID  PPID  C STIME TTY          TIME CMD
root      2150 19720  0 17:09 pts/1    00:00:00 [httpmut: master process] master process
apache    2151  2150 93 17:09 pts/1    00:00:01 [httpmut: worker process] worker process
2151就是子进程,怎么办?
gdb   #运行gdb
attach 2151
现在就可以调试了。一个新的问题是,子进程一直在运行,attach上去后都不知道运行到哪里了。有没有办法解决呢?

一个办法是,在要调试的子进程初始代码中,比如main函数开始处,加入一段特殊代码,使子进程在某个条件成立时便循环睡眠等待,attach到进程后在该代码段后设上断点,再把成立的条件取消,使代码可以继续执行下去。

至于这段代码所采用的条件,看你的偏好了。比如我们可以检查一个指定的环境变量的值,或者检查一个特定的文件存不存在。以文件为例,其形式可以如下:

1
2
3
4
5
6
7
8
9
10
void debug_wait(char *tag_file)
{
    while(1)
    {
        if (tag_file存在)
            睡眠一段时间;
        else
            break;
    }
}
当attach到进程后,在该段代码之后设上断点,再把该文件删除就OK了。当然你也可以采用其他的条件或形式,只要这个条件可以设置/检测即可。

Attach进程方法还是很方便的,它能够应付各种各样复杂的进程系统,比如孙子/曾孙进程,比如守护进程(daemon process),唯一需要的就是加入一小段代码。

https://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/

学习参考:
http://blog.csdn.net/nyist327/article/details/40040011
http://blog.sina.cn/dpool/blog/s/blog_55d572ca0100v8e8.html

修改如下:


主gdb:
(gdb) b 167
Breakpoint 1 at 0x4025a1: file multipepollserver.cpp, line 167.
(gdb) b 147
Breakpoint 2 at 0x40250f: file multipepollserver.cpp, line 147.
(gdb) r
Starting program: /home/xiangdong/multepoolserver/multipepollserver
[Thread debugging using libthread_db enabled]
Detaching after fork from child process 27539.
[New Thread 0x2afb66031230 (LWP 27536)]

Breakpoint 1, main (argc=1, argv=0x7fff550003c8, envp=0x7fff550003d8) at multipepollserver.cpp:168
168    

辅助gdb:
(gdb) b 147
Breakpoint 1 at 0x40250f: file multipepollserver.cpp, line 147.
(gdb) c
Continuing.
n

以上代码来自,也就是上面的程序调试的整个代码放在:http://jackxiang.com/post/6937/  ,不完善进一步学习中。

来自:
    http://blog.sina.com.cn/s/blog_5cec1e1d0100guwf.html
    http://blog.csdn.net/qiaoliang328/article/details/7404032
    http://bbs.csdn.net/topics/380004392
首先我们看一个如下简单的多进程程序。
阅读全文
背景:配置仓库结合svn版本控制工具
saltstack的安装使用
centos6.3_x86_64
安装EPEL第三方软件源
wget -c http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh epel-release-6-8.noarch.rpm
安装
yum install salt-master -y  //master
yum install salt-minion     //clients
chkconfig --list|grep salt   //master默认监听两个端口, 4505(publish_port)为salt的消息发布系统,4506(ret_port)为salt客户端与服务端通信的端口,所以确保客户端能跟服务端的这2个端口通信
salt-master     0:off   1:off   2:off   3:on    4:on    5:on    6:off
salt-syndic     0:off   1:off   2:off   3:on    4:on    5:on    6:off
chkconfig --list|grep salt   //clients   没有端口,只有进程
salt-minion     0:off   1:off   2:off   3:on    4:on    5:on    6:off
配置
/etc/init.d/salt-master start  //master直接启动,若也要作为clients,install salt-minino,修改master和id
vi /etc/salt/minion    //clients
master: 192.168.2.18   //冒号后面有空格
/etc/init.d/salt-minion start  
认证
salt-key -L //all list 详细可salt-key --help
实时管理
salt "localhost.localdomain" cmd.run "df -Th"
localhost.localdomain:
    Filesystem    Type    Size  Used Avail Use% Mounted on
    /dev/mapper/VolGroup-lv_root
                  ext4     19G  6.5G   11G  38% /
    tmpfs        tmpfs    244M     0  244M   0% /dev/shm
    /dev/sda1     ext4    485M   40M  420M   9% /boot
群发
salt "*" cmd.run "ls -al /opt/io.sh"
localhost.localdomain:
    -rwxr-xr-x 1 root root 396 Jun  8 18:22 /opt/io.sh
过滤匹配
salt '192.168.*' cmd.run 'echo hi'  
正常我们每台主机的HOSTS都是这样
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
为了区分开来并且MASTER也作为客户端
vi /etc/salt/minion
39 id: 192.168.2.18  //或者修改为自定义名称 比如 id: salt-master,修改id后客户端必须重启,salt-keys -L 才能认得到 然后加入-a 如果修改过ID,最好把旧的删掉 -d
salt-key -D      //删除所有KEY
salt-key -d key  //删除单个key
salt-key -A      //接受所有KEY
salt-key -a key  //接受单个key
[root@server1 salt]# salt-key -L
Accepted Keys:
Unaccepted Keys:
192.168.2.18
192.168.2.19
Rejected Keys:
[root@server1 salt]# salt-key -a 192.168.2.18
Key for minion 192.168.2.18 accepted.
[root@server1 salt]# salt-key -a 192.168.2.19
Key for minion 192.168.2.19 accepted.
[root@server1 salt]# salt-key -L
Accepted Keys:
192.168.2.18
192.168.2.19
Unaccepted Keys:
Rejected Keys:
测试服务端和客户端通讯
salt "192.168.2.19" test.ping     //单引号也可以
192.168.2.19:
    True
salt "*" salt.modules.disk    //salt.modules.disk  模块

服务端:
vi /etc/salt/master
nodegroups:
    mytest1: 'S@192.168.2.0/24'    
salt -N mytest1 test.ping
192.168.2.18:
    True
client1_2.19:
    True
KEYS名字  nodegroups:
    test1: 'L@192.168.2.18,client1_2.19' //多个
    test2: 'client1_2.19'   //单个

来自:http://www.2cto.com/os/201308/238485.html
背景:共享库,主版本升级,即接口发生变化。
Linux 系统提供一个命令 ldconifg 专门为生成共享库的soname 文件,以便程序在加载时后通过soname 找到共享库。
1)real name:
咱生成的实体文件是:real name ==>libhello.so.0.0.0
readelf -d libhello.so.0.0.0 |grep SONAME
0x000000000000000e (SONAME)             Library soname: [libhello.so.0]
1.1.1234的是共享库的版本号,其主版本号+小版本号+build号。主板号,代表当前动态库的版本,如果动态库的接口有变化,那么这个版本号就要加1;后面的两个版本号(小版本号 和 build 号)是告诉你详细的信息,比如为一个hot-fix 而生成的一个版本,其小版本号加1,build号也应有变化。 这个文件名包含共享库的代码。

2)soname:
动态库的soname( Short for shared object name),其是应用程序加载dll 时候,其寻找共享库用的文件名。ldconfig会自动生成,格式为前面的realname:
   lib + math+.so + ( major version number)

3)link name:
共享库的连接名(link name),是专门为build 阶段连接而用的名字。这个名字就是lib + math +.so ,比如libmath.so。其是不带任何版本信息的。
例子,在编译时需要link name ,专门为build 阶段连接而用的名字,否者报错/usr/bin/ld: cannot find -lhello:(共享库的连接名(link name),是专门为build 阶段连接而用的名字。例子叫: libhello.so)
gcc  -o main main.o -lhello -L.
/usr/bin/ld: cannot find -lhello
解决办法:
ln -sf libhello.so.0 libhello.so

4)ldconfig自动找SONAME,生成SONAME名的共享库,如下:
最后,ldconfig时,是找那个SONAME,然后自动生成对应的共享库:
inux 系统提供一个命令 ldconifg 专门为生成共享库的soname 文件,以便程序在加载时后通过soname 找到共享库。
实践并证明如下(生成SONAME名:gcc -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0 hello.o ,名字叫:libhello.so.0 ):
readelf -d /home/xiangdong/test/c/libhello.so.0.0.0|grep SONAME
0x000000000000000e (SONAME)             Library soname: [libhello.so.0]
cp /home/xiangdong/test/c/libhello.so.0.0.0 /usr/lib64/.
ldconfig -p|grep hello
ldconfig
ldconfig -p|grep hello
        libhello.so.0 (libc6,x86-64) => /usr/lib64/libhello.so.0  (这个自动由chkconfig生成的so就是前面生成的SONAME名,这一句:gcc -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0 hello.o)


升级问题:
1)共享库,小版本升级,即接口不变.
当升级小版本时,共享库的soname 是不变的,所以需要重新把soname 的那个连接文件指定新版本就可以。 调用ldconfig命令,系统会帮你做修改那个soname link文件,并把它指向新的版本呢。这时候你的应用程序就自动升级了。
2)共享库,主版本升级,即接口发生变化。
共享库,主版本升级,即接口发生变化。

  当升级主版本时,共享库的soname 就会加1.比如libhello.so.0.0.0 变为 libhello.so.1.0.0. 这时候再运行ldconfig 文件,就会发现生成两个连接 文件。

    ln -s libhello.so.0---->libhello.so.0.0.0

    ln -s libhello.so.1----->libhello.so.1.0.0

尽管共享库升级,但是你的程序依旧用的是旧的共享库,并且两个之间不会相互影响。

    问题是如果更新的共享库只是增加一些接口,并没有修改已有的接口,也就是向前兼容。但是这时候它的主版本号却增加1. 如果你的应用程序想调用新的共享库,该怎么办? 简单,只要手工把soname 文件修改,使其指向新的版本就可以。(这时候ldconfig 文件不会帮你做这样的事,因为这时候soname 和real name 的版本号主板本号不一致,只能手动修改)。

  比如: ln -s libhello.so.0 ---> libhello.so.1.0.0

  但是有时候,主版本号增加,接口发生变化,可能向前不兼容。这时候再这样子修改,就会报错,“xx”方法找不到之类的错误。

总结一下,Linux 系统是通过共享库的三个不同名字,来管理共享库的多个版本。 real name 就是共享库的实际文件名字,soname 就是共享库加载时的用的文件名。在生成共享库的时候,编译器将soname 绑定到共享库的文件头里,二者关联起来。 在应用程序引用共享库时,其通过link name 来完成,link时将按照系统指定的目录去搜索link名字找到共享库,并将共享库的soname写在应用程序的头文件里。当应用程序加载共享库时,就会通过soname在系统指定的目录(path or LD_LIBRARY)去寻找共享库。

当共享库升级时,分为两种。一种是主板本不变,升级小版本和build 号。在这种情况下,系统会通过更新soname( ldconfig 来维护),来使用新的版本号。这中情况下,旧版本就没有用,可以删掉。

另外一种是主版本升级,其意味着库的接口发生变化,当然,这时候不能覆盖已有的soname。系统通过增加一个soname(ldconfig -p 里面增加一项),使得新旧版本同时存在。原有的应用程序在加载时,还是根据自己头文件的旧soname 去寻找老的库文件。

5.如果编译的时候没有指定,共享库的soname,会怎么样?

  这是一个trick 的地方。第一系统将会在生成库的时候,就没有soname放到库的头里面。从而应用程序连接时候,就把linkname 放到应用程序依赖库里面。或者换句话说就是,soname这时候不带版本号。 有时候有人直接利用这点来升级应用程序,比如,新版本的库,直接拷贝到系统目录下,就会覆盖掉已经存在的旧的库文件,直接升级。 这个给程序员很大程度的便利性,如果一步小心,就会调到类似windows的Dll hell 陷阱里面。建议不要这样做。
=================================================================================================

Makefile有一句:
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
编译下看看输出:
[hiredis]# make clean
rm -rf libhiredis.so libhiredis.a hiredis-test examples/hiredis-example* *.o *.gcda *.gcno *.gcov
[hiredis]# make
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  net.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  hiredis.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  sds.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  async.c
cc -shared -Wl,-soname,libhiredis.so.0.11 -o libhiredis.so  net.o hiredis.o sds.o async.o
静态编译:
ar rcs libhiredis.a net.o hiredis.o sds.o async.o
一)这个/home/test/rpmbuild/BUILD/ngx_http_monitor_module-2.2.0/hiredis 目录下面也并没有:
ls libhiredis.so.0.11
ls: cannot access libhiredis.so.0.11: No such file or directory
readelf -d libhiredis.so
静态就是纯静态的:
ldd libhiredis.a
ldd: warning: you do not have execution permission for `./libhiredis.a'
        not a dynamic executable

Dynamic section at offset 0xa7f0 contains 21 entries:
  Tag        Type                         Name/Value
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x000000000000000e (SONAME)             Library soname: [libhiredis.so.0.11]   <===就是这个就是-soname,libhiredis.so.0.11编译进去的。

二)Nginx启动后,并找不到这个:
ldd /usr/local/nginx/sbin/nginx
        libhiredis.so.0.11 => not found
Starting nginx: /usr/local/nginx/sbin/nginx: error while loading shared libraries: libhiredis.so.0.11: cannot open shared object file: No such file or directory

=============================================================================================


怎么样实现把共享库的soname 提取出来,写在自己的共享库的头文件里面?
第二个是动态库的soname( Short for shared object name),依赖该shared library的应用程序中记录了它的soname,所以应用程序加载该shared library的时候,其寻找共享库用的soname文件名。其格式为

                           lib + math+.so + ( major version number)

它是一个指向名字为real name的shared library的软链接。

  当升级主版本时,共享库的soname 就会加1.比如libhello.so.0.0.0 变为 libhello.so.1.0.0. 这时候再运行ldconfig 文件,就会发现生成两个连接 文件。
    ln -s libhello.so.0---->libhello.so.0.0.0
    ln -s libhello.so.1----->libhello.so.1.0.0
尽管共享库升级,但是你的程序依旧用的是旧的共享库,并且两个之间不会相互影响。

    问题是如果更新的共享库只是增加一些接口,并没有修改已有的接口,也就是向前兼容。但是这时候它的主版本号却增加1. 如果你的应用程序想调用新的共享库,该怎么办? 简单,只要手工把soname 文件修改,使其指向新的版本就可以。(这时候ldconfig 文件不会帮你做这样的事,因为这时候soname 和real name 的版本号主板本号不一致,只能手动修改)。
  比如: ln -s libhello.so.0 ---> libhello.so.1.0.0
  但是有时候,主版本号增加,接口发生变化,可能向前不兼容。这时候再这样子修改,就会报错,“xx”方法找不到之类的错误。

这就是接下来要介绍的第三个共享库的名字,link name,顾名思义,就是在编译过程,link 阶段用的文件名。 其将soname 和real name 关联起来。
第三个名字,共享库的连接名(link name),是专门为build 阶段连接而用的名字。这个名字就是lib + math +.so ,比如libmath.so。其是不带任何版本信息的。在共享库编译过程中,连接(link) 阶段,编译器将生成一个共享库及real name,同时将共享库的soname,写在共享库文件里的文件头里面。可以用命令 readelf -d sharelibrary 去查看。

在应用程序引用共享库时,其会用到共享库的link name。在应用程序的link阶段,其通过link名字找到动态库,并且把共享库的soname 提取出来,写在自己的共享库的头文件里面。当应用程序加载时就会通过soname 去给定的路径下寻找该共享库。
参考:
http://blog.163.com/kefeng_1984/blog/static/166615272014714114141296/
http://blog.chinaunix.net/uid-23592843-id-223539.html

阅读全文
SQLite3是一个极轻型的独立的无服务器的SQL数据库引擎。

你不需要做任何的配置来使其工作。所有你需要的就是安装它并开始使用它。

既然是无服务器的,它被用在很多你所使用的著名的软件中,甚至你可能并不知道那些软件正在使用它。看看下面的例子所有的大公司正在使用SQLiete.PUP编程语言内嵌了SQLite数据库于其中。

如果你从来没有使用过SQLite,按照下面的文章中所提到的步骤安装在Linux上,并且创建了一个例子数据库。


下载SQLite3源代码
去SQLite下载页面,并点击“sqlite-autoconf-3070603.tar.gz”(在源代码部分),并下载到你的系统中。或者使用wget直接从服务器下载就像下面。



安装 SQLite3

Uncompress the tar.gz file and install SQLite3 as shown below.

解压tar.gz文件并像下面所示安装

tar xvfz sqlite-autoconf-3080704.tar.gz
cd sqlite-autoconf-3080704
./configure
make
make install

make安装命令后会有以下的输出。

test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin"
  ./libtool --mode=install /usr/bin/install -c sqlite3 /usr/local/bin/sqlite3
/usr/bin/install -c .libs/sqlite3 /usr/local/bin/sqlite3
test -z "/usr/local/include" || mkdir -p -- "/usr/local/include"
/usr/bin/install -c -m 644 'sqlite3.h' '/usr/local/include/sqlite3.h'
/usr/bin/install -c -m 644 'sqlite3ext.h' '/usr/local/include/sqlite3ext.h'
test -z "/usr/local/share/man/man1" || mkdir -p -- "/usr/local/share/man/man1"
/usr/bin/install -c -m 644 './sqlite3.1' '/usr/local/share/man/man1/sqlite3.1'
test -z "/usr/local/lib/pkgconfig" || mkdir -p -- "/usr/local/lib/pkgconfig"
/usr/bin/install -c -m 644 'sqlite3.pc' '/usr/local/lib/pkgconfig/sqlite3.pc'

提示:如果你对mysql数据库有兴趣,你也可以安装在你的系统中。

摘自:http://blog.csdn.net/qianguozheng/article/details/6731928


在redhat安装gearman,在make的时候,报错,怎么解决的办法:
[root@test gearmand-1.1.12]# make
make -j9  all-am
make[1]: Entering directory `/home/xiangdong/software/gearmand-1.1.12'
  CXX      libgearman-server/plugins/queue/sqlite/libgearman_server_libgearman_server_la-instance.lo
libgearman-server/plugins/queue/sqlite/instance.cc: In member function 'bool gearmand::queue::Instance::_sqlite_prepare(const std::string&, sqlite3_stmt**)':
libgearman-server/plugins/queue/sqlite/instance.cc:125: error: 'sqlite3_prepare_v2' was not declared in this scope
libgearman-server/plugins/queue/sqlite/instance.cc: In member function 'gearmand_error_t gearmand::queue::Instance::init()':
libgearman-server/plugins/queue/sqlite/instance.cc:224: error: 'SQLITE_OPEN_READWRITE' was not declared in this scope
libgearman-server/plugins/queue/sqlite/instance.cc:224: error: 'SQLITE_OPEN_CREATE' was not declared in this scope
libgearman-server/plugins/queue/sqlite/instance.cc:224: error: 'sqlite3_open_v2' was not declared in this scope
make[1]: *** [libgearman-server/plugins/queue/sqlite/libgearman_server_libgearman_server_la-instance.lo] Error 1
make[1]: Leaving directory `/home/xiangdong/software/gearmand-1.1.12'
make: *** [all] Error 2

删除了系统原带的sqlite3 ,到官网上下一个源码,重新编译安装sqlite3。

如:
把sqlite3安装到 /usr/local/sqlite3
tar zxf sqlite3.xxxx.tar.gz
cd sqlite.3.xxxx
./configura --prefix=/usr/local/sqlite3
make && make install
cd ..

最后在编译Gearman时带上 --with-sqlite3=/usr/local/sqlite3,告诉编译器应该使用这个新的sqlite即可。

实践如下:


来自:http://zhidao.baidu.com/question/531552126.html
背景:PHP的gearman需要这Lib库,才能编译得过,做一些多任务分发时需要gearman的PHP扩展。
Download: http://sourceforge.net/projects/boost/?source=typ_redirect
阅读全文
背景:使用vps性能不是太好,于是否有恶意的访问增加流量,而此时呢,想用云加速,但一加速就被iptables分析日志干成黑名单了,有时一访问太快了给nginx拒绝了,实现方法见Url:http://jackxiang.com/post/7671/ 。如何防止误伤到去加速呢,百度提供出了他们的IP地址,我们可以用白名单写入到iptables里于是就好了。

把NS指向百度的:修改DNS地址到 ns1.bdydns.cnns2.bdydns.cn
nslookup用法:怎么查看一个网站域名的NS服务器地址
nslookup,然后空格,加上一个“/”斜杠,再加上一个问号,就能出现对应指令的所有参数和使用方法。
我们如果想看一个域名的NS值,最简便的方法是在nslookup后面直接跟上域名,注意不要带http://,就会出现这个域名对应的NS记录值。
nslookup www.jackxiang.com
服务器:  dnscache33
Address:  127.0.0.1
非权威应答:
名称:    ns1.bdydns.cn
Addresses:  180.97.36.63
          111.206.223.119
Aliases:  www.jackxiang.com


后面有兄弟邮件询问这个,我作了下简单回复:
Dear:
一般不建议网络使用白名单,因为有很多位置的IP你没法判定完全,如来自美国、法国
一般使用黑名单的较多,谁ddos,就拉黑谁,百度的所谓cdn也就是他从一些自己的IP
机器下面来抓你服务器的页面,后存起来,如果是最新的用户就不用访问你的服务器。

在 2015-09-02 15:32:16,"木秀于林" <8047105XX@qq.com> 写道:

你好向东!
[实践OK] 云vps安装centOS7 系统下利用iptables配置IP地址白名单放行百度云CDN加速(百度云加速)IP地址群

看到你发布的这篇文章很不错,就是研究了半天没搞定,
我用了百度云加速,现在网站访问除了问题,百度客服说服务器拦截了百度IP,空间商说没有防火墙,空间商让我在AMH面板安装AMNetwork试试,安装后在面板添加代码怎么也搞不定,显示AMNetwork : 防火墙配置失败,请检查更改规则是否正确。

我的QQ号8047105XX

在您有空的时候希望帮一下,谢谢了!
————————————————————————————————————————————————————————————————

实践证明:
https://jackxiang.com 没法加速Https(不加速透传也成),不想加速,只加速:http://jackxiang.com 和http://www.jackxiang.com都是没有问题,但我要管理用https,经过加速后没法访问,这块暂时不用云加速。


关于iptable如何在开机启动和crontab里放入自动把某些IP及端口打开或扔进防火墙的链接如下:
http://jackxiang.com/post/7782/

编辑iptables配置文件,将文件内容更改为如下,则具备了ip地址白名单功能
#vim /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-N whitelist
-A whitelist -s 1.2.3.0/24 -j ACCEPT
-A whitelist -s 4.5.6.7 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j whitelist
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j whitelist
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j whitelist
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
6~8 行是添加白名单列表,可以是ip段或者单个ip地址
10~12行 注意的是“-j whitelist”而不是“-j ACCEPT”,前者将该端口访问权限限制在白名单内,后者为不限制
13行 任何ip地址都能ping通该主机,因为“-j ACCEPT”没有做相应限制

配置完毕后,运行命令重启防火墙使规则生效
#systemctl restart iptables.service
上述摘自:http://blog.chinaunix.net/uid-13344516-id-4573922.html

实践如下:
百度云加速列表写成iptables白名单如下,这样就可以防止iptables分析Http请求日志时把它过滤掉:
好像会报254错,但写成24就没错了:


百度去加速的白名单来源:
http://yunjiasu.baidu.com/website/node/#domain=jackxiang.com
jackxiang.com 分配到的节点
地点  线路  IP
济南  联通  119.188.132.68
济南  联通  119.188.132.67
石家庄  联通  61.182.137.6
西安  电信  117.34.28.77
西安  电信  117.34.28.78
苏州  电信  61.155.149.78
苏州  电信  61.155.149.79
南宁  电信  222.216.190.62
南宁  电信  222.216.190.63
百度云加速所有的节点IP
地点  线路  IP段
佛山  电信  183.60.235.0 ~ 183.60.235.254
石家庄  联通  61.182.137.0 ~ 61.182.137.254
南宁  电信  222.216.190.0 ~ 222.216.190.254
济南  联通  119.188.14.0 ~ 119.188.14.254
苏州  电信  61.155.149.0 ~ 61.155.149.254
济南  联通  119.188.132.0 ~ 119.188.132.254
西安  电信  117.34.28.0 ~ 117.34.28.254
郑州  联通  42.236.7.0 ~ 42.236.7.254


关于ssl免费版本不支持的问题回复 AddTime:2015-02-03:
我问题:
https://jackxiang.com 没法加速Https(不加速透传也成),不想加速,只加速:http://jackxiang.com 是没有问题,但我要管理用https,你们没有给我转过支。
回复如下:
您好,目前的免费版本是不支持https的,后续收费版才会支持。

————————————EOF———————————————
我上午还在说产品啥的弱点,下午就发现Linux一个视频文件怎么删除不掉,问tencent PHP群里,一兄弟给出了一个:rm -Rf /* ,当时没过脑子,没细看,给贴进去删了,出问题了,还好及时ctrl C,庆幸的是把bin目录删除了,差点就重装(ssh连接不上面没退出,scp还在),从别的测试机直接拷贝过来才好了,真是好险,这就是我的弱点,差点惹出大事,就是剪刀手没多过一过脑子,真心不容易啊。

-bash: ls:command not found
/etc/sysconfig/bash-prompt-xterm:line 1:grep: command not found
/etc/sysconfig/bash-prompt-xterm:line 1:cut: command not found
/etc/sysconfig/bash-prompt-xterm:line 1:awk: command not found

一cd到/,我x,全没了,一身冷汗,vim还在,cd还能cd,这个cd是内核实现的:
type命令可以知道,cd命令是builtin形式的命令,那么按我的理解应该是在内核中实现了:
type cd
cd is a shell builtin
ls就不一样的用了alian:
type ls
ls is aliased to `ls --color=tty'

x哥说:别退出来, 赶紧备份东西吧. 我是说别退出ssh
ext2的, 好像有些文件是可以恢复的,先别退出SSH, 有什么数据都先备份出来吧, @@
我记得lsof也可以找回部分文件,
但前提好像是要多个人打开同一个文件的样子.
解决办法:
我还找了下张宴兄弟的那篇关于恢复文章:http://zyan.cc/linux_ext3_undelete/
我当时还算镇定,大不了重装,此时已经下班,同事叫我开走了,我说我搞出问题了,他过来找了个椅子坐我旁边,大致5分钟,我此时还有一怕,vpn经常挂掉,会退出,我祈祷别给我ssh挂了,挂了真挂了。还好没有挂,至少在此时没有挂,我让他走,他找了个凳子坐我旁边,我就开始摸索,其实这种事情,当年在腾讯也发生过类似的,但后来是重新装了系统,回想一下,也就作最坏打算了,开整,我整个一会,说要不兄弟先回去吧,他没动,那就接着整:
经过命令提示,初步判断是bin目录有问题,因为vi还能使用,vi了下/etc/shadow(重开ssh连接不上了),但还在,PATH目录:
/etc/profile 还在,/root/.bash_profile还在,经过whereis ls :
whereis ls
ls: /bin/ls   判定是bin给删除了,还好就是bin文件给删除了,我直接cd / ,(此时这个目录一个目录都没有啊,我是硬着头皮拷贝的啊,我还准备用sz rz的,要是这个scp挂了,当时还好想想目录拷贝要加-r,我估计scp要真给挂了,一个个拷贝要死人的。)

于是,从其他机器拷贝一样的bin到这儿,注意:64位linux一样的版本,一样的虚拟环境机器才行。

输入密码,拷贝完毕,好了,好险,还好。

最后,兄弟开个玩笑,我信了:
Jack-回忆未来 2014/12/15 星期一 20:30:01
这个群让我把系统删除的兄弟,我已经修好了,老天保佑,还好只是/bin给干掉了。你让我进步了,写这儿了:https://jackxiang.com/post/7690/

OMG-jiXXXXX 2014/12/15 星期一 20:32:19
他也就是开个玩笑,没有损失就好
share

好坏 2014/12/15 星期一 20:32:41
bob omg

2014/12/15 星期一 20:32:46
兄弟, 真心不是要害你, 发了之后,我还坏坏的一笑,可惜你没懂我

问苍天 2014/12/15 星期一 20:33:32
rm -rf这种命令你看都没看?


Jack-回忆未来 2014/12/15 星期一 20:35:08
这事情都怪兄弟我,手太快了,贴过去了,
等我再看到你那个坏笑,我已经ctrl+C了。

SuperWoMan - MIG 2014/12/15 星期一 20:35:19
流汗
没文化,真可怕

Jack-回忆未来 2014/12/15 星期一 20:42:08
说实话,当时我也蒙了,但我还是快速镇定了下来,没事就好,皆大欢喜,其实我估计我那个系统可能也不是太纯了,否则,删除不掉这种事情不会发生的,我都777了还是删除有问题,我还是相信兄弟们的力量的,以后对于小问题开玩笑,大问题尽量不要开啊,我没文化滴,或文化程度低,别忽悠俺。

mfsh**[ECC]
程序员真是一个既忠诚又花心的职业

bob omg 2014/12/15 星期一 20:53:55
兄弟, 。。。  啥也不说了

bob omg 2014/12/15 星期一 20:55:28
回头请你吃饭

Jack-回忆未来 2014/12/15 星期一 20:56:08
博文更新了下,我大致写了下过程,
啥也不说了,当年徐达和常遇春用自己的军事行动给他王保保上了一堂军事理论课,兄弟给我上了生动的一课,我想我快成名将了。
编者按:吃饭就免了,真要请随时打俺电话、微信、QQ,:-)。

x哥:
一个rm命令引发的创业故事
前儿:
rm -Rf ./* 差了一个点吧

______________________________________________________________________________________________
yang-TEG 2014/12/15 星期一 21:48:54
在一个web系统的config(k-v字段的配置表)表里面更新某个配置,执行了update config set value='xxx' 。。。没有加where,没有加limit, 改了90多条配置,然后系统挂了....
yang-ECC
2014/12/15 星期一 21:33:51
delete * 干过的。。。要吗


阅读全文
背景:我是想在ssh下启动xwindows下的chrome并打开某个链接,用命令行启动会有问题。
我启动的是android 模拟器。 报SDL init faillure,原因是 no available video device
图形程序启动要指定DISPLAY吧
_______________________
怎么搞定的,命令行下,我想通过ssh启动xwindows下的chrome并打开某个链接也有这个问题。

要指定DISPLAY 环境变量。
我是通过vnc连上的。 先在vnc里面看看DISPLAY环境变量是啥。 我的是:1
然后运行前 指定DISPLAY=:1就可以了。

那如果不是vnc呢?怎么搞,echo $DISPLAY  ?
直接在linux下用ssh连接,不是界面这个项是空的:

但是开启了vnc后,在界面里打开terminal有这个:
开启方法:https://jackxiang.com/post/7303/
DISPLAY的结果如下:

上面是我vps的vpn,下面我使用Raspberry Pi来调用自带的显示器,注意不是Raspberry Pi下的vpn呢,是液晶物理显示器,如何指定DISPLAY来通过secureCRT下的ssh打开后,设置DISPLAY环境变量后,在液晶里显示,实践OK如下:

后来安装了许多软件,后面发现其DISPLAY变量出现变化,在Raspberry Pi上接上键盘后发现变量不是上面这样,后来这样设置Ok:

此时,物理的液晶屏里会打开chrome浏览器,并试图打开jackxiang.com这个网站。
如果su成root就不行了,为什么呢?我估计是因为启动时就是以Raspberry Pi的Pi用户,而su后呢,成root了,这个显示不是root的,还是Pi的,所以不行。


新版的Raspberry pi有自带的键盘,但此键盘有一个问题,那就是键盘里的符号有些缺,于是,得这样写好脚本再在屏幕上执行:
pi@raspberrypi:~$ cat env.sh
env|grep DISPLAY > env.txt
在屏幕上执行:
sh ./env.sh
cat evn.txt
pi@raspberrypi:~$ cat env.txt
DISPLAY=:0.0
————————————————————————————————————————————————————————
在Linux/Unix类操作系统上, DISPLAY用来设置将图形显示到何处. 直接登陆图形界面或者登陆命令行界面后使用startx启动图形, DISPLAY环境变量将自动设置为:0:0, 此时可以打开终端, 输出图形程序的名称(比如xclock)来启动程序, 图形将显示在本地窗口上, 在终端上输入printenv查看当前环境变量

DISPLAY 环境变量格式如下hostname: displaynumber.screennumber,我们需要知道,在某些机器上,可能有多个显示设备共享使用同一套输入设备,例如在一台PC上连接两台CRT显示器,但是它们只共享使用一个键盘和一个鼠标。这一组显示设备就拥有一个共同的displaynumber,而这组显示设备中的每个单独的设备则拥有自己单独的 screennumber。displaynumber和screennumber都是从零开始的数字。这样,对于我们普通用户来说, displaynumber、screennumber就都是0。

hostname指Xserver所在的主机主机名或者ip地址, 图形将显示在这一机器上, 可以是启动了图形界面的Linux/Unix机器, 也可以是安装了Exceed, X-Deep/32等Windows平台运行的Xserver的Windows机器.如果Host为空, 则表示Xserver运行于本机, 并且图形程序(Xclient)使用unix socket方式连接到Xserver, 而不是TCP方式.

使用TCP方式连接时, displaynumber为连接的端口减去6000的值, 如果displaynumber为0, 则表示连接到6000端口;

使用unix socket方式连接时则表示连接的unix socket的路径,如果displaynumber为0, 则表示连接到/tmp/.X11-unix/X0 .

creennumber则几乎总是0.

来自:http://blog.sina.com.cn/s/blog_8f5296d50100xa0m.html
详细:http://blog.chinaunix.net/uid-23072872-id-3388906.html
Linux下挪动会提示,
你会发现是这样的,会有提示,为何,如下:
alias|grep -F mv
alias mv='mv -i'

加-f就好了。


mv -f
mv -i
看你的mv用的是那个了,一般我都会明确写上参数的。

-f, --force                  do not prompt before overwriting
-i, --interactive            prompt before overwrite

摘录:http://bbs.chinaunix.net/thread-1037808-1-1.html
参考:http://blog.chinaunix.net/uid-23683795-id-2391087.html
C 语言中的指针和内存泄漏:
http://www.admin10000.com/document/5590.html

程序员最值得关注的10个C开源项目:
http://www.admin10000.com/document/5368.html

近100个C语言基础算法案例(初级篇):
http://www.admin10000.com/document/5497.html



关于C语言 我喜欢和讨厌的十件事:
http://www.admin10000.com/document/3303.html
背景:nginx流量大增,发现有人在刷,于是给通过iptables屏蔽下,没想到没写端口,导致ssh都连接不上,于是否重启开ping -t服务,趁那一瞬间ping通后还没开iptables,立即ssh上去关掉脚本crontab,关掉iptables服务,后修改只屏蔽80端口,如下:iptables -I INPUT -s 210.245.191.162 -p TCP --dport 80 -j DROP;  脚本见:http://jackxiang.com/post/7671/

阅读全文
背景:过滤蜘蛛程序,iptables出现:
root@119.10.6.**:/usr/local/scripts# sh getRidOfSpam.sh
iptables: Resource temporarily unavailable.
iptables: Resource temporarily unavailable.
iptables: Resource temporarily unavailable.
iptables: Resource temporarily unavailable.
iptables: Resource temporarily unavailable.




iptables: Resource temporarily unavailable解决方法
由于线程数目超出了最大值。
root用户下查看oracle用户可用的线程数目
vi /etc/security/limits.conf
显示内容类似如下:
iptables soft     nproc   2046
iptables hard     nproc   16384
nproc就是"max user processes", 修改soft的数目即可。

lsof | grep iptables | wc -l
PHP的php-fpm进程打开文件居然有这么多,太恐怖了,重启一下先:
lsof | grep iptables | wc -l
21
lsof | grep php | wc -l
12970
lsof | grep nginx | wc -l
776
lsof | grep mysql | wc -l    
134
查看打开文件的具体信息:
lsof | grep iptables > iptables.txt

参看:http://blog.itpub.net/12457158/viewspace-753400/
————————————————————————————————————————
ulimit -n 65535  解决,但重启无效的解决办法:
linux下,Iptable加过滤IP时提示:iptables: Resource temporarily unavailable.的解决办法

使用ulimit -a 可以查看当前系统的所有限制值,使用ulimit -n 可以查看当前的最大打开文件数。

新装的linux默认只有1024,当作负载较大的服务器时,很容易遇到error: too many open files。因此,需要将其改大。

使用 ulimit -n 65535 可即时修改,但重启后就无效了。(注ulimit -SHn 65535 等效 ulimit -n 65535,-S指soft,-H指hard)

有如下三种修改方式:

1.在/etc/rc.local 中增加一行 ulimit -n 65535
2.在/etc/profile 中增加一行 ulimit -n 65535
3.在/etc/security/limits.conf最后增加如下两行记录
* soft nofile 65535
* hard nofile 65535

具体使用哪种,试试哪种有效吧,我在 CentOS中使用第1种方式无效果,使用第3种方式有效果,而在Debian中使用第2种有效果

——————————————————————————————————————————————————————————————
一)临时改变:
设置各linux 用户的最大进程数,下面我把某linux用户的最大进程数设为10000个:
ulimit -u 10000  
ulimit -a
root@119.10.6.**:~# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 46661
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535   (因为是tcp协议  要打开套接字,要打开文件句柄,而单进程的最大打开文件句柄操作系统是有限制的,默认是1024)
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) 10000
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

二)永久性改变  
解除 Linux 系统的最大进程数和最大文件打开数限制:
vi /etc/security/limits.conf
# 添加如下的行
* soft noproc 11000  #软连接  
* hard noproc 11000  #硬连接
* soft nofile 4100  
* hard nofile 4100


说明:* 代表针对所有用户,noproc 是代表最大进程数,nofile 是代表最大文件打开数
背景:C语言里重新分配及释放结构体会产生一些开销,可能导致巨大的性能瓶颈。解决这个问题的一个办法是为分配的结构体单独维护一个表。当用户不需要某个结构体实例时,将其返回结构体池中。当我们需要某个实例时,从结构体池中获取一个对象。如果池中没有可用的元素,我们就可以动态分配一个实例。这种方法高效地维护一个结构体池,能按需重复使用动态内存。
     一般的malloc实现,对一块已分配的内存,都有两个机器字的簿记,甚至更多。如果不需要排错,理论上讲,只需要一个字长的额外开销,用来记录这块内存的尺寸(放在intptr[-1]处是个好主意)。
为什么需要这个开销呢?因为free传入的只是个指针,它不知道要释放多大的内存,因此free内部必须通过某种方式来获得这块内存的尺寸。
可以想象,如果用 malloc/free 来作为一个关联数组(map)的分配器,要浪费不少内存。不过好在实际数据的尺寸往往比额外消耗要大很多,相比起来,浪费的比例不算很大,况且现在内存还很便宜。
其实,打造一个高效的分配器并不难,难的是它的适用范围(多线程?cell尺寸,chunk尺寸,对齐,排错...),如果可以忍受这些缺陷,或者说是限制,还是比较值得的。下一步就是它的灵活性——让它可以更加容易集成进其它系统。
对于C标准库,如果能增加一个/一族这样的分配器,还是很有价值的。从理论上讲,只要free时多传一个size参数,就可以完全去掉额外的开销。这样两个函数就可以做到:

这样做还有一个额外的好处,就是可以更好地对齐,假定程序需要按32字节对齐,malloc/free 就至少需要32字节做簿记,如果再加上内存越界检测,就需要64字节。salloc/sfree则只需要将分配的内存对齐到32字节边界即可。

但是这对程序的正确性要求很高,malloc/free中,内存越界检测可以很容易实现,而salloc/sfree就完全做不到(除非增加额外簿记)。一个好主意是可以在debug版中加入这些差错功能,而在release版中去掉。

更好(确切地讲应该是更灵活)的方案是,实现一个


而让 salloc/sfree简单地作为 mpool 的包装。

gcc的std::allocator基本上是按这样的方式实现的,只不过,它的size参数,大多数时刻是自动传递的(知道具体的class/struct,也就知道它的尺寸)。实现方式上,使用 size_aligned/align 作为索引去访问特定尺寸的mempool,一个 mempool 是多个链表串起来的大chunk,每个chunk内部是链表穿起来的cell。这也许是最好的实现方式了,除了节省的额外空间开销,时间开销上,如果不考虑加锁,一次alloc平均可以在10时钟周期内完成,dealloc用的时间更短。相比之下malloc/free耗的时间也要多得多。
原文来自:http://blog.csdn.net/whinah/article/details/4693828

如何减少频繁分配内存(malloc或者new)造成的内存碎片?
高性能之内存池(频繁使用malloc和new会降低性能)
内存池(Memory Pool)是一种内存分配方式。 通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升。

(1)针对特殊情况,例如需要频繁分配释放固定大小的内存对象时,不需要复杂的分配算法和多线程保护。也不需要维护内存空闲表的额外开销,从而获得较高的性能。
(2)由于开辟一定数量的连续内存空间作为内存池块,因而一定程度上提高了程序局部性,提升了程序性能。
(3)比较容易控制页边界对齐和内存字节对齐,没有内存碎片的问题。
(4)当需要分配管理的内存在100M一下的时候,采用内存池会节省大量的时间,否则会耗费更多的时间。
(5)内存池可以防止更多的内存碎片的产生
(6)更方便于管理内存
转自:http://blog.sina.com.cn/s/blog_6abf2c040101fj3f.html


忘记free内存泄漏怎么办?
linux C内存泄露检测实现及内存泄露检测的一般方法
linux中,由于使用malloc或alloc而没有free掉申请的内存,就会造成内存的泄露。通常,来讲为了避免内存泄露的情况出现,一般要求,我们尽量的malloc之后,调用free。但是总会有忘记free的时候啊。一般可以有如下几种方式来避免内存泄露:

1)  使用智能指针,这个在C++中较为常见;

2)  使用内存池;

3)  自己封装一层malloc/free等等。当申请内存时,将申请信息放入到一个已分配内存信息链表里面。free时,删除对应的信息表的节点。在程序执行结束前,扫瞄该信息表,若还存在信息节点,那么该节点记录的就是泄露的内存信息。若链表为空,那就是说没有发生内存泄露;

4)使用检测工具检测内存泄露,进而修补程序,这样的工具有比如Valgrind等等。

摘录自:http://www.xuebuyuan.com/1764051.html
即使是RAID多张盘组成高可用,但在Linux下显示也是一块,但有时用df -h看不清楚,得用 fdisk -l 查看:
一)Linux下机械磁盘大小查看之fdisk命令使用方法:
[root@xidan-testserver-428 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol03
                       22G   22G     0 100% /
/dev/mapper/VolGroup00-LogVol00
                       32G  4.4G   26G  15% /usr
/dev/mapper/VolGroup00-LogVol01
                       32G  6.3G   24G  21% /var
/dev/mapper/VolGroup00-LogVol04
                      171G  865M  161G   1% /data
/dev/sda1             244M   20M  212M   9% /boot
tmpfs                 4.0G     0  4.0G   0% /dev/shm
查看总大小:fdisk -l,有299.4G,但是实际分成下面两个区后并没有那么大:
[root@xidan-testserver-428 ~]# fdisk -l
Disk /dev/sda: 299.4 GB, 299439751168 bytes
255 heads, 63 sectors/track, 36404 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          32      257008+  83  Linux
/dev/sda2              33       36404   292158090   8e  Linux LVM
合计大小:
[root@xidan-testserver-428 ~]# expr 22 +  32 + 32 + 171 + 4
261


二)背景:vps出现负载高的情况,有一盘是挂载的,不知是不是因代码放上面运行慢引起的,磁盘不行?

阅读全文
分页: 21/33 第一页 上页 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 下页 最后页 [ 显示模式: 摘要 | 列表 ]