编程的一些杂散知识

Author: sx                                                          E-mail:598726409@qq.com

资料整理于自己的笔记(有许多的图片和代码块没有添加,后面会慢慢补齐),也有些是博客之类 ,如有侵权,请及时联系我,我会及时删除。因为都是手码的笔记,可能会有些错别字,理解有误的地方请联系我,以便及时修改。

Volatile

volatile 的意思是“易失的,易改变的”。这个限定词的含义是向编译器指明变量的内容可能会由于其他程序的修改而变化。通常在程序中申明了一个变量时,编译器会尽量把它存放在通用寄存器中,例如ebx。当CPU把其值放到ebx中后就不会再关心对应内存中的值。若此时其他程序(例如内核程序或一个中断)修改了内存中它的值,ebx中的值并不会随之更新。为了解决这种情况就创建了volatile限定词,让代码在引用该变量时一定要从指定位置取得其值。
       关键字volatile有什么含意?并给出三个不同的例子。 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
       回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
       假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:
int square(volatile int *ptr)
{return *ptr * *ptr;}
下面是答案:
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr) 
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr) 
{
int a;
a = *ptr;
return a * a; }
 
volatile的本意是“易变的”  

由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:

static   int   i=0;

int   main(void)
{
        ...
        while   (1)
        {
                if   (i)   dosomething();
        }
}

/*   Interrupt   service   routine.   */
void   ISR_2(void)
{
          i=1;
}

程序的本意是希望ISR_2中断产生时,在main当中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此
可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。如果将将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

一般说来,volatile用在如下的几个地方:

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

2、多任务环境下各任务间共享的标志应该加volatile;

3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实
现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。

//=============
指针类型也是一种变量,所以也是可以用volatile来修饰的.

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如

操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行

优化,从而可以提供对特殊地址的稳定访问。

使用该关键字的例子如下:

int   volatile   nVint;

当要求使用volatile   声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指

令刚刚从该处读取过数据。而且读取的数据立刻被保存。

例如:

volatile   int   i=10;
int   a   =   i;
。。。//其他代码,并未明确告诉编译器,对i进行过操作
int   b   =   i;

volatile   指出   i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的

汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间

的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果

i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问


注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编

代码,测试有无volatile关键字,对程序最终代码的影响:

首先用classwizard建一个win32   console工程,插入一个voltest.cpp文件,输入下面的代码:

#include   <stdio.h>
void   main()
{
  int   i=10;
  int   a   =   i;

  printf( "i=   %d\n ",a);
                //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道
  __asm   {
    mov                   dword   ptr   [ebp-4],   20h
  }

  int   b   =   i;
  printf( "i=   %d\n ",b);
}

然后,在调试版本模式运行程序,输出结果如下:
i   =   10
i   =   32

然后,在release版本模式运行程序,输出结果如下:
i   =   10
i   =   10

输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。

下面,我们把   i的声明加上volatile关键字,看看有什么变化:


#include   <stdio.h>
void   main()
{
  volatile   int   i=10;
  int   a   =   i;

  printf( "i=   %d\n ",a);
  __asm   {
    mov                   dword   ptr   [ebp-4],   20h
  }

  int   b   =   i;
  printf( "i=   %d\n ",b);
}

分别在调试版本和release版本运行程序,输出都是:
i   =   10
i   =   32

这说明这个关键字发挥了它的作用!
linux目录详解

linux目录架构
/ 根目录
/bin 常用的命令 binary file 的目錄
/boot 存放系统启动时必须读取的档案,包括核心 (kernel) 在内
/boot/grub/menu.lst GRUB设置
/boot/vmlinuz 内核
/boot/initrd 核心解壓縮所需 RAM Disk
/dev 系统周边设备
/etc 系统相关设定文件
/etc/DIR_COLORS 设定颜色
/etc/HOSTNAME 设定用户的节点名
/etc/NETWORKING 只有YES标明网络存在
/etc/host.conf 文件说明用户的系统如何查询节点名
/etc/hosts 设定用户自已的IP与名字的对应表
/etc/hosts.allow 设置允许使用inetd的机器使用
/etc/hosts.deny 设置不允许使用inetd的机器使用
/etc/hosts.equiv 设置远端机不用密码
/etc/inetd.conf 设定系统网络守护进程inetd的配置
/etc/gateways 设定路由器
/etc/protocols 设定系统支持的协议
/etc/named.boot 设定本机为名字服务器的配置文件
/etc/sysconfig/network-scripts/ifcfg-eth0 设置IP
/etc/resolv.conf 设置DNS
/etc/X11 X Window的配置文件,xorg.conf 或 XF86Config 這兩個 X Server的設定檔
/etc/fstab 记录开机要mount的文件系统
/etc/inittab 设定系统启动时init进程将把系统设置成什么样的runlevel
/etc/issue 记录用户登录前显示的信息
/etc/group 设定用户的组名与相关信息
/etc/passwd 帐号信息
/etc/shadow 密码信息
/etc/sudoers 可以sudo命令的配置文件
/etc/securetty 设定哪些终端可以让root登录
/etc/login.defs 所有用户登录时的缺省配置
/etc/exports 设定NFS系统用的
/etc/init.d/ 所有服務的預設啟動 script 都是放在這裡的,例如要啟動或者關閉
/etc/xinetd.d/ 這就是所謂的 super daemon 管理的各項服務的設定檔目錄
/etc/modprobe.conf 内核模块额外参数设定
/etc/syslog.conf 日志设置文件
/home 使用者家目录
/lib 系统会使用到的函数库
/lib/modules kernel 的相关模块
/var/lib/rpm rpm套件安装处
/lost+found 系統不正常產生錯誤時,會將一些遺失的片段放置於此目錄下
/mnt 外设的挂载点
/media 与/mnt类似
/opt 主机额外安装的软件
/proc 虚拟目录,是内存的映射
/proc/version 内核版本
/proc/sys/kernel 系统内核功能
/root 系统管理员的家目录
/sbin 系统管理员才能执行的指令
/srv 一些服務啟動之後,這些服務所需要取用的資料目錄
/tmp 一般使用者或者是正在執行的程序暫時放置檔案的地方
/usr 最大的目录,存许应用程序和文件
/usr/X11R6: X-Window目录
/usr/src: Linux源代码
/usr/include:系统头文件
/usr/openwin 存放SUN的OpenWin
/usr/man 在线使用手册
/usr/bin 使用者可執行的 binary file 的目錄
/usr/local/bin 使用者可執行的 binary file 的目錄
/usr/lib 系统会使用到的函数库
/usr/local/lib 系统会使用到的函数库
/usr/sbin 系统管理员才能执行的指令
/usr/local/sbin 系统管理员才能执行的指令
/var 日志文件
/var/log/secure 記錄登入系統存取資料的檔案,例如 pop3, ssh, telnet, ftp等都會記錄在此檔案中
/var/log/wtmp 記錄登入者的訊息資料, last
/var/log/messages 幾乎系統發生的錯誤訊息
/var/log/boot.log 記錄開機或者是一些服務啟動的時候,所顯示的啟動或關閉訊息
/var/log/maillog 紀錄郵件存取或往來( sendmail 與 pop3 )的使用者記錄
/var/log/cron 記錄 crontab 這個例行性服務的內容
/var/log/httpd, /var/log/news, /var/log/mysqld.log, /var/log/samba,/var/log/procmail.log:
分別是幾個不同的網路服務的記錄檔

如何查看已经安装的deb包的版本号?

命令格式apt list 软件包名
deb是debian linus的安装格式,跟red hat的rpm非常相似,最基本的安装命令是: dpkg -i file.deb
dpkg 是Debian Package的简写,是为Debian 专门开发的套件管理系统,方便软件的安装、更新及移除。所有源自Debian的Linux发行版都使用dpkg,例如Ubuntu、Knoppix 等。
以下是一些 Dpkg 的普通用法:
1、dpkg -i <package.deb>
安装一个 Debian 软件包,如你手动下载的文件。
2、dpkg -c <package.deb>
列出 <package.deb> 的内容。
3、dpkg -I <package.deb>
从 <package.deb> 中提取包裹信息。
4、dpkg -r <package>
移除一个已安装的包裹。
5、dpkg -P <package>
完全清除一个已安装的包裹。和 remove 不同的是,remove 只是删掉数据和可执行文件,purge 另外还删除所有的配制文件。
6、dpkg -L <package>
列出 <package> 安装的所有文件清单。同时请看 dpkg -c 来检查一个 .deb 文件的内容。
7、dpkg -s <package>
显示已安装包裹的信息。同时请看 apt-cache 显示 Debian 存档中的包裹信息,以及 dpkg -I 来显示从一个 .deb 文件中提取的包裹信息。
8、dpkg-reconfigure <package>
重新配制一个已经安装的包裹,如果它使用的是 debconf (debconf 为包裹安装提供了一个统一的配制界面)。

Linux中查看文件有多少行

使用wc命令 具体通过wc --help 可以查看。
如: wc -l filename 就是查看文件里有多少行
       wc -w filename 看文件里有多少个word。
        wc -L filename 文件里最长的那一行是多少个字。
 
wc命令
  wc命令的功能为统计指定文件中的字节数、字数、行数, 并将统计结果显示输出。
 
  语法:wc [选项] 文件…
  说明:该命令统计给定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所有指定文件的总统计数。字是由空格字符区分开的最大字符串。
  该命令各选项含义如下:
  - c 统计字节数。
  - l 统计行数。
  - w 统计字数。
  这些选项可以组合使用。
  输出列的顺序和数目不受选项的顺序和数目的影响。
  总是按下述顺序显示并且每项最多一列。
  行数、字数、字节数、文件名
  如果命令行中没有文件名,则输出中不出现文件名。
  例如:
  $ wc - lcw file1 file2
  4 33 file1
  7 52 file2
  11 11 85 total
  省略任选项-lcw,wc命令的执行结果与上面一样。
使用ls -lht命令显示当前目录下的所有文件,其中有一列就是显示这个文件的大小。
如果要看一个文件夹的大小,可以用du -sh *

Linux下如何添加用户

想到要创建一个用户的时候,我们马上想到了useradd命令或者在图像下进行建立,但是这样并没有真正的了解linux用户的生成步骤,我们知道在linux下“一切皆文件”,那么对于一个用户来说通常包括以下几个文件值得我们去注意:
/etc/passwd (用户)
/etc/group (用户组)
/etc/shadow (密钥文件)
/home/username (家目录)
/etc/skel/.* (骨架文件)
一、常用命令:
(1)创建用户命令两条:
adduser
useradd
(2)用户删除命令:
userdel

二、两个用户创建命令之间的区别
adduser: 会自动为创建的用户指定主目录、系统shell版本,会在创建时输入用户密码。
useradd:需要使用参数选项指定上述基本设置,如果不使用任何参数,则创建的用户无密码、无主目录、没有指定shell版本。

----------------------------------------------------------分割线----------------------------------------------------------
Linux用户管理 http://www.linuxidc.com/Linux/2014-05/101238.htm
Linux用户管理命令 http://www.linuxidc.com/Linux/2012-05/60754.htm
Linux 用户管理常用命令 http://www.linuxidc.com/Linux/2013-05/84734.htm
Linux用户、组的管理常用到的命令介绍 http://www.linuxidc.com/Linux/2013-05/84989.htm
Linux_用户、组和权限问题 http://www.linuxidc.com/Linux/2013-12/94358.htm
Linux 的用户和组命令 http://www.linuxidc.com/Linux/2013-05/83950.htm
----------------------------------------------------------分割线----------------------------------------------------------

Linux下查看信息常用命令

一、linux CPU大小
  cat /proc/cpuinfo |grep "model name" && cat /proc/cpuinfo |grep "physical id"
说明:Linux下可以在/proc/cpuinfo中看到每个cpu的详细信息。但是对于双核的cpu,在cpuinfo中会看到两个cpu。常常会让人误以为是两个单核的cpu。
二、内存大小
cat /proc/meminfo |grep MemTotal
free -m 查看系统内存占用
三、硬盘大小
fdisk -l |grep Disk
四、   uname -a # 查看内核/操作系统/CPU信息的linux系统信息命令
五、head -n 1 /etc/issue # 查看操作系统版本,是数字1不是字母L
六、cat /proc/cpuinfo # 查看CPU信息的linux系统信息命令
七、hostname # 查看计算机名的linux系统信息命令
八、lspci -tv # 列出所有PCI设备
九、lsusb -tv # 列出所有USB设备的linux系统信息命令
十、lsmod # 列出加载的内核模块
十一、env # 查看环境变量资源
十二、free -m # 查看内存使用量和交换区使用量
十三、df -h # 查看各分区使用情况
十四、du -sh # 查看指定目录的大小
十五、grep MemTotal /proc/meminfo # 查看内存总量
十六、grep MemFree /proc/meminfo # 查看空闲内存量
十七、uptime # 查看系统运行时间、用户数、负载
十八、cat /proc/loadavg # 查看系统负载磁盘和分区
十九、mount | column -t # 查看挂接的分区状态
二十、fdisk -l # 查看所有分区
二十一、swapon -s # 查看所有交换分区
二十二、hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备)
二十三、dmesg | grep IDE # 查看启动时IDE设备检测状况网络
二十四、ifconfig # 查看所有网络接口的属性
二十五、iptables -L # 查看防火墙设置
二十六、route -n # 查看路由表
二十七、netstat -lntp # 查看所有监听端口
二十八、netstat -antp # 查看所有已经建立的连接
二十九、netstat -s # 查看网络统计信息进程
三十、ps -ef # 查看所有进程
三十一、top # 实时显示进程状态用户
三十二、w # 查看活动用户
三十三、id # 查看指定用户信息
三十四、last # 查看用户登录日志
三十五、cut -d: -f1 /etc/passwd # 查看系统所有用户
三十六、cut -d: -f1 /etc/group # 查看系统所有组
三十七、crontab -l # 查看当前用户的计划任务服务
三十七、chkconfig –list # 列出所有系统服务
三十八、chkconfig –list | grep on # 列出所有启动的系统服务程序
三十九、rpm -qa # 查看所有安装的软件包
四十、cat /proc/cpuinfo :查看CPU相关参数的linux系统命令
四十一、cat /proc/partitions :查看linux硬盘和分区信息的系统信息命令
四十二、cat /proc/meminfo :查看linux系统内存信息的linux系统命令
四十三、cat /proc/version :查看版本,类似uname -r
四十四、cat /proc/ioports :查看设备io端口
四十五、cat /proc/interrupts :查看中断
四十六、cat /proc/pci :查看pci设备的信息
四十七、cat /proc/swaps :查看所有swap分区的信息

查看系统中的存储设备(文件系统查看)
du -参数  filename
du常用的选项:
  -h:以人类可读的方式显示
  -a:显示目录占用的磁盘空间大小,还要显示其下目录和文件占用磁盘空间的大小
  -s:显示目录占用的磁盘空间大小,不要显示其下子目录和文件占用的磁盘空间大小
  -c:显示几个目录或文件占用的磁盘空间大小,还要统计它们的总和
  --apparent-size:显示目录或文件自身的大小
  -l :统计硬链接占用磁盘空间的大小
  -L:统计符号链接所指向的文件占用的磁盘空间大小
  一、du -h:这个就不多说了。
  二、du -a:使用此选项时,显示目录和目录下子目录和文件占用磁盘空间的大小
切换到Root模式下在  fdisk -l 查看
df -lh 
ls filename -lh 以友好模式查看文件

SHELL脚本

shell脚本调试
Shell提供了一些用于调试脚本的选项,如下所示:
-n   读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
-v   一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
-x   提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
文件操作符
Linux Shell提供了大量的文件操作符,这样可以完成测试文件的各种操作。比较常用的文件操作符如下表所示:
-d file         测试file是否为目录
-e file         测试file是否存在
-f file          测试file是否为普通文
-r file          测试file是否是可读文件
-s file          测试file的长度是否不为0
-w file         测试file是否是可写文件
-x file          测试file是否是可执行文件
-L file          测试file是否符号化链接

Linux中VIM的行号设置

方法一:
1、显示当前行行号,在VI的命令模式下输入
:nu
2、显示所有行号,在VI的命令模式下输入
:set nu
方法二:
使用vi编辑~/.vimrc文件,在该文件中加入一行"set nu",添加内容不含引号, 命令如下:
vi ~/.vimrc
方法三:
在UBUNTU中vi的配置文件存放在/etc/vim目录中,配置文件名为vimrc 
在Fedora中vi的配置文件存放在/etc目录中,配置文件名为vimrc
在Red Hat Linux 中vi的配置文件存放在/etc目录中,配置文件名为vimrc
使用vi编辑该文件,在该文件中加入一行"set nu",添加内容不含引号。如Ubuntu命令:
vi /etc/vim/vimrc


Linux中查找某个字符

grep -rn "hello,world!" *
grep xxx *.*
 
* : 表示当前目录所有文件,也可以是某个文件名
-r 是递归查找
-n 是显示行号
-R 查找所有文件包含子目录
-i 忽略大小写
下面是一些有意思的命令行参数:
 
grep -i pattern files :不区分大小写地搜索。默认情况区分大小写, 
grep -l pattern files :只列出匹配的文件名, 
grep -L pattern files :列出不匹配的文件名, 
grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配‘magic’,而不是‘magical’), 
grep -C number pattern files :匹配的上下文分别显示[number]行, 
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行, 
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。 
这里还有些用于搜索的特殊符号:
 
\< 和 \> 分别标注单词的开始与结尾。
例如: 
grep man * 会匹配 ‘Batman’、‘manic’、‘man’等, 
grep '\<man' * 匹配‘manic’和‘man’,但不是‘Batman’, 
grep '\<man\>' 只匹配‘man’,而不是‘Batman’或‘manic’等其他的字符串。 
'^':指匹配的字符串在行首, 
'$':指匹配的字符串在行尾,  
 
2,xargs配合grep查找
find -type f -name '*.php'|xargs grep 'GroupRecord'
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值