Andy Niu Help
1.0.0.0
|
详细描述
变量说明
linux下printf函数输出不及时 |
1、考虑下面的代码: #include <stdio.h> int main(int argc, char* argv[]) { printf("hello "); printf("world"); getchar(); return 0; } 2、在windows下面没有问题,正常输出。但是在linux下面,printf输出不及时。 3、原因是:在linux系统下,printf函数是行缓冲式的输出,当printf遇到\n时,或者缓冲区满时, 才会将缓冲区里的内容刷新到标准输出(stdout). 4、怎么解决这个问题? a、输出的结尾加上\n b、或者在printf后面,调用 fflush(stdout) 如下: #include <stdio.h> int main(int argc, char* argv[]) { printf("hello \n"); printf("world"); fflush(stdout); getchar(); return 0; } 5、奇怪的是,调用过一次 fflush(stdout); 之后,以后都会实时刷新,不知道为什么。
- 参见
linux下有关的目录 |
/ : this is root directory root 用户根目录 /bin : commands in this dir are all system installed user commands 系统的一些指令 /sbin : commands in this dir are all system installed super user commands 超级用户指令系统管理命令,这里存放的是系统管理员使用的管理程序 /usr/bin: user commands for applications 后期安装的一些软件的运行脚本 /usr/sbin: super user commands for applications 超级用户的一些管理程序 主目录:/root、/home/username 用户可执行文件:/bin、/usr/bin、/usr/local/bin 系统可执行文件:/sbin、/usr/sbin、/usr/local/sbin 其他挂载点:/media、/mnt 配置:/etc 临时文件:/tmp 内核和Bootloader:/boot 服务器数据:/var、/srv 系统信息:/proc、/sys 共享库:/lib、/usr/lib、/usr/local/lib 每个用户都拥有一个主目录。所有用户的个人文件(配置、数据甚至应用程序)都放在其中。 根的主目录为/root。大多数非根主目录包含在 /home 树中,通常以用户命名。 重要的二进制位于 /bin(用户二进制)以及 /sbin(系统二进制)中。 不重要的二进制(如图形环境或Office 工具)安装在 /usr/bin 和 /usr/sbin中。 进行这种分隔是为了尽可能地缩小根分区。使用源代码编译的软件通常位于 /usr/local/bin 和 /usr/local/sbin中。 注意:usr很多人误以为是user的简写,实际上是unix system resource的简写
Linux换行符 |
1、空白字符包括:空格符,制表符,换行符 2、Windows换行符为\r\n, 使用notepad++显示所有字符,显示CRLF,使用linux cat -A 显示^M$ 3、Linux换行符为\n, 使用notepad++显示所有字符,显示LF,使用linux cat -A 显示$ 4、在Linux下面,如何去除^M? 我们知道^M这个字符就是\r,因此可以对\r进行替换 sed "s/\r//g" -i 111 或者直接对^M进行替换,需要注意的是,不能直接输入^和M,必须使用Ctrl+V,然后Ctrl+M,表示空白字符\r sed "s/^M//g" -i 111
- 参见
linux提示符设置 |
1、新建用户登陆后,发现命令提示符如下: -bash-3.2$ 2、设置命令提示符,选项如下: \d :代表日期,格式为weekday month date,例如:"Mon Aug 1" \H :完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux \h :仅取主机的第一个名字,如上例,则为fc4,.linux则被省略 \t :显示时间为24小时格式,如:HH:MM:SS \T :显示时间为12小时格式 \A :显示时间为24小时格式:HH:MM \u :当前用户的账号名称 \v :BASH的版本信息 \w :完整的工作目录名称。家目录会以 ~代替 \W :利用basename取得工作目录名称,所以只会列出最后一个目录 \# :下达的第几个命令 \$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$ 3、示例如下: -bash-3.2$ export PS1='[\u @\W]' [niu @~]cd /home [niu @home]
Linux文件命名 |
1、xxx.d是目录,这里的d是directory,比如rc.d 2、xxxd是守护进程文件,也就是服务进程文件,这里的d是daemo,比如mysqld,httpd 3、rc文件,这个有争议,一说是run command,一说是run control,是脚本类文件,程序启动时运行的脚本。
linux查看历史操作记录 |
1、命令是history,列出当前用户最新的10条操作记录,如下: [root@localhost ~]# history 10 691* 2016-09-27 16-27-29 root: 692* 2016-09-27 16-28-23 root: 693 2016-09-27 16-31-03 root: history 694 2016-09-27 16-31-24 root: history 10 695 2016-09-27 16-37-58 root: history 696 2016-09-27 16-38-03 root: history 10 697 2016-09-27 16-38-48 root: ll 698 2016-09-27 16-38-50 root: ll -a 699 2016-09-27 16-39-06 root: more .bash_history 700 2016-09-27 16-39-52 root: history 10 会列出操作者和操作时间。 2、history只能列出当前用户的操作记录,也就是说,用户A不能查看用户B的操作记录。 3、注意:连续两次相同的操作,不会重复记录,如下: [root@localhost dmu]# history 10 702 2016-09-27 16-42-15 root: history 703 2016-09-27 16-45-11 root: cd /usr/local/datafs/IBP 704 2016-09-27 16-45-14 root: cd dmu 705 2016-09-27 16-45-17 root: ./dmu_start.sh 706 2016-09-27 16-45-29 root: history 10 707 2016-09-27 16-45-52 root: history|grep dmu_start.sh 708 2016-09-27 16-46-44 root: ll 709 2016-09-27 16-46-56 root: history 710 2016-09-27 16-47-03 root: ll 711 2016-09-27 16-47-06 root: history 10 [root@localhost dmu]# history 10 702 2016-09-27 16-42-15 root: history 703 2016-09-27 16-45-11 root: cd /usr/local/datafs/IBP 704 2016-09-27 16-45-14 root: cd dmu 705 2016-09-27 16-45-17 root: ./dmu_start.sh 706 2016-09-27 16-45-29 root: history 10 707 2016-09-27 16-45-52 root: history|grep dmu_start.sh 708 2016-09-27 16-46-44 root: ll 709 2016-09-27 16-46-56 root: history 710 2016-09-27 16-47-03 root: ll 711 2016-09-27 16-47-06 root: history 10 4、根据操作序号,引用操作,如下: [root@localhost dmu]# history 10 702 2016-09-27 16-42-15 root: history 703 2016-09-27 16-45-11 root: cd /usr/local/datafs/IBP 704 2016-09-27 16-45-14 root: cd dmu 705 2016-09-27 16-45-17 root: ./dmu_start.sh 706 2016-09-27 16-45-29 root: history 10 707 2016-09-27 16-45-52 root: history|grep dmu_start.sh 708 2016-09-27 16-46-44 root: ll 709 2016-09-27 16-46-56 root: history 710 2016-09-27 16-47-03 root: ll 711 2016-09-27 16-47-06 root: history 10 [root@localhost dmu]# !711 history 10 702 2016-09-27 16-42-15 root: history 703 2016-09-27 16-45-11 root: cd /usr/local/datafs/IBP 704 2016-09-27 16-45-14 root: cd dmu 705 2016-09-27 16-45-17 root: ./dmu_start.sh 706 2016-09-27 16-45-29 root: history 10 707 2016-09-27 16-45-52 root: history|grep dmu_start.sh 708 2016-09-27 16-46-44 root: ll 709 2016-09-27 16-46-56 root: history 710 2016-09-27 16-47-03 root: ll 711 2016-09-27 16-47-06 root: history 10
Linux环境常用库的介绍 |
库 头文件 描述 libGL.so <GL/gl.h> 实现到OpenGL API的接口 libGLU.so <GL/glu.h> 实现到OpenGL API的接口 libImlib.so <Imlib.h> 实现一套图像处理例程 libc.so 无 实现标准C库(不需要头文件) libcom_err.so <com_err.h> 实现出错处理例程的集合 libcrypt.so <crypt.h> 实现加密函数的集合 libcurses.so <curses.h> 光标字符模式的屏幕操作库 libdb.so <db.h> 创建和操作数据库的库 libdl.so <dlfcn.h> 让程序在运行时加载和使用库代码而无须在编译时链接库 libform.so <form.h> 实现字符模式应用程序的窗体处理能力 libglib.so <glib.h> Glib库,提供了大多数程序需要的大量基本工具函数,比如散列表等 libgthread.so <glib.h> 实现对Glib的线程支持 libgtk.so <gtk/gtk.h> GIMP下的X库 libhistory.so <readline/readline.h> 实现GNU readline(libreadline)包中的命令行历史机制 libjpeg.so <jpeglib.h> 定义到JPEG库的接口,赋予应用程序使用JPEG图像文件的能力 libm.so <math.h> 实现标准C数学库 libmenu.so <menu.h> 提供在字符模式屏幕上创建和使用菜单的例程 libncurses.so <ncurses.h> 使用ncurses文本模式屏幕控制系统的应用程序的基础库 libnss.so <nss.h> 用于名字服务切换工具的功能,提供了名字数据库比如DNS接口 libpanel.so <panel.h> 提供在字符模式屏幕上创建和使用面板的例程 libpbm.so <pbm.h> 可移植的位图库,实现了使用多种格式单色位图的接口 libpgm.so <pgm.h> 可移植的灰度图库,实现了使用多种格式灰色位图的接口 libpng.so <png.h> 用于编码,解码和操作PNG格式图像文件的参考实现 libpnm.so <pnm.h> 可移植anymap库是使用多种位图格式的基础库 libppm.so <ppm.h> 可移植的像素图库实现了使用多种格式彩色像素图的接口 libpthread.so <pthread.h> 实现了POSIX线程库,标准的Linux多线程库 libreadline.so <readline/readline.h> GNU readline包的基础库,该软件包能够让应用软件存储,记忆并且编辑命令行. libresolv.so <resolv.h> 提供使用因特网域名服务器和服务的接口 libslang.so <slang.h> 提供方便的脚本语言S-lang,用于嵌入其它应用程序 libtiff.so <tiffio.h> 读写TIFF格式图像文件的库 libz.so <zlib.h> 通用压缩例程库 libvga.so <vga.h> Linux的底层VGA和SVGA图形库
Linux统计文件、文件夹的个数 |
1、当前目录下文件的个数 [niu_zibin@localhost time]$ ll|grep '^-'|wc -l 2、当前目录下文件夹的个数 [niu_zibin@localhost time]$ ll|grep '^d'|wc -l 3、在当前目录下递归,统计文件的个数 [niu_zibin@localhost time]$ ll -R|grep '^-'|wc -l 4、在当前目录下递归,统计文件夹的个数 [niu_zibin@localhost time]$ ll -R|grep '^d'|wc -l
linux进程通信__发送信号的函数 |
1、信号是unix中最古老的进程通信的一种方式,他是软件层次上对中断机制的模拟,是一种异步通信方式. 信号可以实现用户空间进程和内核空间进程的交互,内核进程可以利用他通知用户空间进程发生了哪些系统事件. 我们可以任何时候给进程发送信号而无需知道进程的状态,如果进程当前并未处于执行态,则信号则会由内核保存起来. 如果进程是阻塞状态,那么信号传递会被延迟,直到阻塞结束时才会传递给进程。 2、查看所有的信号,如下: [root@localhost mysql]# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX 3、前32种信号会有各种不同的名称,后32种会以“SIGRTMIN”或者“SIGRTMAX”开头。 前者是从unix继承下来的信号,称为不可靠信号(也称为非实时信号)。 后者为了解决“不可靠信号”的问题进行了更改和扩充的信号形成了可靠信号(也称为实时信号) 4、如果想要了解可靠与不可靠信号,需要了解信号的生命周期: 一个完整的信号周期可以分为三个重要阶段,三个重要阶段有四个重要事件刻画的: 信号产生,信号在进程中注册,信号在进程中注销,执行信号处理函数 5、可靠信号与不可靠信号的区别: 不可靠信号如果发现信号已经在进程中注册,就会忽略该信号,因此若前一个信号还没有注销又产生了新的信号就是导致信号丢失。 可靠信号发送给一个进程时,不管该信号是否已经在进程中注册,都会被再注册一次,因此信号不会丢失。 所有可靠信号都支持排队,所有不可靠信号都不支持排队。 注:这里信号的产生,注册,注销等是指信号的内部的实现机制,而不是调用信号的函数实现。 所以信号注册与否,与本节后面讲到的发送信号函数(kill等)以及信号安装函数(signal()等)无关,只与信号值有关。 6、用户进程对信号的响应有三种方式: 忽略信号,对信号不做任何处理,但是又两个信号是不能忽略的,即SIGKILL,SIGSTOP 捕捉信号,定义信号处理函数,当信号发送时,执行相应的自定义处理函数 执行缺省操作,linux对每种信号都规定了默认操作 7、kill()方法 kill()函数和熟知的kill系统命令一样,可以发送信号给信号和进程组(实际上kill系统命令只是对kill函数的一个简单封装) 需要注意的是他不仅可以终止进程(发送SIGKILL信号),也可以向进程发送其他信号。 8、raise()方法 与kill函数不同的是raise()函数允许进程向自身发送信号。 9、alarm()方法 alarm()也称为闹钟函数,可以在进程中设置一个定时器,等到时间到达时,就会想进程发送SIGALARM信号。 注意的是一个进程只能有一个闹钟时间,如果调用alarm()之前已经设置了闹钟时间,那么任何以前的闹钟时间都会被新值所代替 10、pause()方法 此函数用于将进程挂起直到捕捉到信号为止,这个函数很常用,通常用于判断信号是否已到
shell如何输入制表符 |
1、ctrl,按下v,再按下i
system与popen |
1、脚本如下: [root@localhost localconfig]# more niu.sh #! /bin/sh set -x sleep 5 echo 'over' 2、使用system调用,如下: #include <stdio.h> #include <stdlib.h> int main(int argc,char* argv[]) { char script[256] = {0}; sprintf(script,"./niu.sh"); system(script); return 0; } 3、使用popen调用,如下: #include <stdio.h> #include <stdlib.h> int main(int argc,char* argv[]) { char script[256] = {0}; sprintf(script,"./niu.sh"); printf("Exe Script[%s]", script); FILE* fp = popen(script,"r"); pclose(fp); return 0; } 4、这里存在问题,由于脚本执行需要5秒钟,导致程序卡住5秒,怎么办? 把脚本放入后台运行,如下: sprintf(script,"./niu.sh &"); 5、system与popen的区别: system和popen都是执行了类似的运行流程,大致是fork->execl->return。 但是我们看到system在执行期间调用进程会一直等待shell命令执行完成(waitpid等待子进程结束)才返回, 但是popen无须等待shell命令执行完成就返回了。 我们可以理解system为串行执行,在执行期间调用进程放弃了”控制权”,popen为并行执行。 popen中的子进程没人给它收尸了啊?是的,如果你没有在调用popen后调用pclose那么这个子进程就可能变成僵尸。 6、另外一个重要的区别是:popen可以与标准IO流进行交互。如果存在交互过程,即使脚本放入后台运行,如下: #include <stdio.h> #include <stdlib.h> int main(int argc,char* argv[]) { char script[256] = {0}; sprintf(script,"./niu.sh &"); // system(script); printf("Exe Script[%s]", script); FILE* fp = popen(script,"r"); char outBuf[256] = {0}; fread(outBuf,1024,1,fp); printf("Exe Result:%s",outBuf); pclose(fp); return 0; } 为什么? 很好理解,因为要进行输入,或者获取输出。
tty__pty__pts__ptmx |
1、tty(终端设备的统称) tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息的东西。 后来这东西被键盘与显示器取代,所以现在叫终端比较合适。 终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。 2、pty(虚拟终端): 但是如果我们远程telnet到主机或使用xterm时不也需要一个终端交互么?是的,这就是虚拟终端pty(pseudo-tty) 3、pts/ptmx(pts/ptmx结合使用,进而实现pty) pts(pseudo-terminal slave)是pty的实现方法,与ptmx(pseudo-terminal master)配合使用实现pty。
打包deb包 |
1、示例脚本如下: #! /bin/sh set -x set -e # read -p "please input version like 1.0.0: " version name="masterkeymgr" version="1.0.0" underline="_" platform="amd64" projName=${name}${underline}${version}${underline}${platform} debName=${projName}".deb" # 脚本所在目录 shPath=$(cd $(dirname $0);pwd) cd $shPath/../ if [ ! -d "./dist" ] ; then mkdir "./dist" fi cd ./dist rm -fr * mkdir DEBIAN cat>"./DEBIAN/control"<<EOF package: $name version: $version architecture: $platform maintainer: niuzibin description: this is masterkeymgr deb EOF mkdir -p ./usr/lib cp $shPath/../lib/libmasterkeymgr.so ./usr/lib mkdir -p ./usr/include cp $shPath/../src/masterkeymgr/masterkeymgr.h ./usr/include cd $shPath/../ sudo dpkg -b dist $debName
获取脚本所在的绝对路径 |
1、pwd是工作目录,不是脚本所在的目录,所谓工作目录就是:在哪个目录下面工作。 考虑脚本aa.sh中有 echo $(pwd),从aa.sh所在目录调用aa.sh,回显aa.sh所在目录。 但是,从目录A去调用aa.sh,回显目录A,从目录B去调用aa.sh,回显目录B 特别注意:从不同的目录调用aa.sh,后面的参数不同,因为需要指定aa.sh的位置。 也就是说,从哪个目录去调用【也就是工作目录】,pwd就是哪个目录。 2、下面使用python来举例说明: a、os.getcwd():获取当前工作目录,也就是在哪个目录下运行这个程序。 举例来说:假设F:\aaa\bbb\ccc目录下有个文件 TestDir.py,打印当前工作目录。进入windows命令行窗口: 在F:\aaa\bbb\ccc运行 python TestDir.py,输出F:\aaa\bbb\ccc 在F:\aaa\bbb运行 python ccc/TestDir.py,输出F:\aaa\bbb 在F:\aaa运行 python bbb/ccc/TestDir.py,输出F:\aaa b、如果我想获取TestDir.py文件所在的目录,怎么办? 使用sys.path[0] 如下: import os print(os.getcwd()) import sys print(sys.path[0],end='') 3、如何获取脚本所在的决定路径呢? shPath=$(cd $(dirname $0);pwd) echo $shPath cd $(dirname $0) 进入脚本所在目录,工作目录变化,pwd获取工作目录,也就是脚本所在目录,返回工作目录的值。 4、注意:$(cd $(dirname $0);pwd)返回后,工作目录还是原来的工作目录。 要想改变工作目录,使用cd $(dirname $0),不能获取命令的返回值。 为什么? 可以认为,获取命令的返回值,相当于进入新的工作目录,返回后,又退出新的工作目录,回到原来的工作目录。 5、$(dirname $0) 返回第一个参数的目录,第一个参数就是脚本。没有必要,转到目录,再pwd,直接获取返回值就好了。如下: SHELL_HOME=`dirname $0`
虚拟内存和常驻内存 |
1、考虑下面的代码,如下: #include <string> #include <vector> using namespace std; int main(int argc, char* argv[]) { int i=0; vector<char*> pVec; while(true) { printf("num=%d\n",i++); //fflush(stdout); usleep(2000*1000); //sleep(2); char* pc = new char[1024*1024]; pc = new char[1024*1024]; memset(pc,0,1024*1024); pVec.push_back(pc); } return 0; } 2、程序每次new出1M,然后再new出1M,前面的1M不使用,使用后面的1M。使用top|grep main,打印如下: 32596 root 15 0 13084 6016 760 S 0.0 1.2 0:00.00 root main 32596 root 15 0 15140 7048 760 S 0.0 1.4 0:00.00 root main 32596 root 15 0 17196 8080 760 S 0.0 1.6 0:00.00 root main 32596 root 15 0 19252 9112 760 S 0.0 1.8 0:00.00 root main 32596 root 15 0 21308 9.9m 760 S 0.0 2.0 0:00.00 root main 32596 root 15 0 23364 10m 760 S 0.0 2.2 0:00.00 root main 32596 root 15 0 25420 11m 760 S 0.0 2.4 0:00.00 root main 32596 root 15 0 27476 12m 760 S 0.0 2.6 0:00.00 root main 32596 root 15 0 29532 13m 760 S 0.0 2.8 0:00.00 root main 32596 root 15 0 31588 14m 760 S 1.0 3.0 0:00.01 root main 32596 root 15 0 31588 14m 760 S 0.0 3.0 0:00.01 root main 32596 root 15 0 33644 15m 760 S 0.0 3.2 0:00.01 root main 3、可以看到VIRT每次增加2M,而RES每次增加1M,SHR是共享内存,不变化。 刚开始的时候,单位是KB,RES大于10M,使用M作为单位。 4、为什么VIRT每次增加2M,而RES每次增加1M? VIRT是虚拟内存,包括常驻内存和交换到硬盘的内存。 RES是常驻内存,每次new出2M,只有1M使用,在常驻内存,另外1M没有使用。 可以认为Linux操作系统很聪明,没有使用的1M直接交换到硬盘中。 5、怎么看出交换出去的内存大小? top命令后,按下f,按下p选中p: SWAP = Swapped size (kb),然后回车,可以看到 32661 root 15 0 29532 13m 760 S 1.0 2.8 0:00.02 root 14m main VIRT 29532 KB RES 13M SWAP 14M 6、看进程是否内存泄露,要看VIRT虚拟内存,因为程序有些内存分配了,却从来没有使用,这也是内存泄露。 7、同样的程序,在Windows下面,表现不一样,在Windows虚拟内存和常驻内存大小差不多。 在windows如何查看虚拟内存? 任务管理器-->查看-->选择列-->内存-提交大小就是虚拟内存 而内存-专用工作集就是常驻内存
运行缺少库 |
1、运行缺少库,需要添加依赖库的路径,有两种办法。 2、第一种办法: export LD_LIBRARY_PATH = xxx 3、第二种办法: 修改 /etc/ld.so.conf 添加路径, 然后执行 ldconfig
Copyright (c) 2015~2016, Andy Niu @All rights reserved. By Andy Niu Edit.