Love Sun

Linux

2038年问题

前言 在计算机应用上,2038年问题可能会导致某些软件在2038年无法正常工作。所有使用POSIX时间表示时间的程序都将受其影响,因为它们的时间起点是格林尼治时间1970年1月1日0时0分0秒(这个时间名叫 the Unix Epoch),它们用the Unix Epoch经过的秒数(忽略闰秒)来表示时间。这种时间表示法在类Unix(Unix-like)操作系统上是一个标准,并会影响以其C编程语言开发给其他大部份操作系统使用的软件。在大部分的32位操作系统上,此“time_t”数据模式使用一个有符号32位整数(signed int32)存储计算的秒数。依照此“time_t”标准,在此格式能被表示的最后时间是第2147483647秒(代表格林尼治时间2038年1月19日凌晨03:14:07)。下一秒,即格林尼治时间2038年1月19日凌晨03:14:08,由于32位整型溢出,时间将会被“绕回”(wrap around)成一个负数,变成了第 -2147483648 秒(代表格林尼治时间1901年12月13日20:45:52),造成应用程序发生严重的时间错误,而无法运行。 正文 也许大家都已经知道计算机的2000年问题是什么概念,但是什么时候又冒出来一个2038年问题的呢? 用C语言编制的程序不会碰到2000年问题,但是会有2038年问题。这是因为,大多数C语言程序都使用到一个叫做“标准时间库”的程序库,这个时间库用一个标准的4字节也就是32位的形式来储存时间信息。 当初设计的时候,这个4字节的时间格式把1970年1月1日凌晨0时0分0秒(这个时间名叫 the Unix Epoch)作为时间起点,这时的时间值为0。以后所有的时间都是从这个时间开始一秒一秒累积得来的。 比方说如果时间已经累积到了919642718这个数值,就是说这时距离 the Unix Epoch已经过去了919642718秒,换算一下就应该是1999年2月21日16时18分38秒。 这样计算时间的好处在于,把任意两个时间值相减之后,就可以很迅速地得到这两个时间之间相差的秒数,然后你可以利用别的程序把它换算成明白易懂的年月日时分秒的形式。 要是你曾经读过一点儿关于计算机方面的书,你就会知道一个4字节也就是32位的存储空间的最大值是2147483647,请注意!2038年问题的关键也就在这里———当时间一秒一秒地跳完2147483647那惊心动魄的最后一秒后,你猜怎么样? 答案是,它就会转为负数也就是说时间无效。那一刻的准确的时间为2038年1月19日星期二凌晨03:14:07,之后所有用到这种“标准时间库”的C语言程序都会碰到时间计算上的麻烦。 这就是2038年问题。 但是大家也不用太过紧张。2038年问题比千年虫(the Millennium bug)问题解决起来相对要容易一些,只要给那些程序换一个新版本的“标准时间库”就可以了,比如说,改用8字节64位的形式来存储时间。这样做并不怎么费事,因为在C程序中“标准时间库”是相对独立的一个部分,里面的时间表达都有自己的一套时间类型和参数(而在碰到Y2K的那些大型主机中,时间格式大都没有一)。 说到这里,一些冰雪聪明的菜鸟DDMM们应该可以联想到,WindowsNT用的是64位操作平台,它的开始时间是1601年1月1日———但是它每过1个纳秒就跳一下,因此,WindowsNT它会碰到的是2184年问题…… 而在一些用64位来表示时间的平台上,例如DigitalAlpha、SGI、Sparc等等,想要看到它们的时间出错你得等到天荒地老———那大概是2920亿年。到那时,位于猎户座旋臂的太阳,已经是黑矮星或暗黑物质,猎户座旋臂已经被重力波震断,银河系大概则已经变成小型似星体了。 所以,给那些准备攒机的菜鸟DD一个建议,除非您想要把资料流传给下一个宇宙,一台64位的电脑已经足够。 总之,32位的最后时间是2038年1月19日03:14:07,星期二。 64位的最后时间约2900亿年后的292,277,026,596年12月4日15:30:08,星期日。 refer to:http://blog.csdn.net/linyt/article/details/52728910

Linux下,多线程程序死循环问题调试

当你的软件在某个时刻停止服务,CPU占用达到100%+,这种问题一个可能的原因是产生了死循环,假设程序某处存在潜在的死循环,并在某种条件下会引发,本文以一个示例来定位出现死循环的位置。 当程序某处存在死循环,通常定位问题及缩小范围的方法是,在可疑的代码处加log,或者注释掉可疑代码,这对于容易重现问题的程序来说还好,但对于“偶尔”才会产生问题程序却很难调试,因为我们很难重现程序故障。本文所述的调试过程正是在这种情况下,假设问题已经出现,我们要求环境保护现场,即出问题的程序还在运行中。 1.我们首先要知道是哪个线程出了问题: 首先查一下出问题进程的pid,例如

然后top命令查看线程信息:

从上面可以看出,出问题线程PID为11073 2.接下来,我们用gdb来attach目标进程 执行:

在gdb中,列出线程状态:

gdb已经列出了各线程正在执行的函数,我们需要更多信息,记住11073对应的行首标号,这是gdb为线程分配的id,这里为2,然后执行切换:

bt一下:

来看一下101行的代码:

现在我们定位到了出问题的代码位置,这里的循环只用来演示的。 最后别忘了detach refer to:http://www.cppblog.com/elva/archive/2010/08/02/121943.html

Linux下定位进程被谁KILL

今天上午有个同事问,自己的进程被莫名其妙的杀死了,想知道是被那个进程误杀了。 第一个想法是用kernel hack系统调用的方式,刚打算翻出hook的代码,想起了貌似audit不就是干这个的吗 #auditctl -a exit,always -S kill #auditctl -l #tail -f /var/log/audit/audit.log 加上这个规则后,再用kill杀死一个进程就可以看到是谁干的了。 type=SYSCALL msg=audit(1446528422.179:18502): arch=c000003e syscall=62 success=yes exit=0 a0=53f a1=8 a2=0 a3=53f items=0 ppid=1427 pid=2613 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=tty1 ses=1 comm=”bash” exe=”/usr/bin/bash”…

Linux大文件传输

我们经常需要在机器之间传输文件。比如备份,复制数据等等。这个是很常见,也是很简单的。用scp或者rsync就能很好的完成任务。但是如果文件很大,需要占用一些传输时间的时候,怎样又快又好地完成任务就很重要了。在我的测试用例中,一个最佳的方案比最差的方案,性能提高了10倍。 复制文件 如果我们是复制一个未压缩的文件。这里走如下步骤: 压缩数据 发送到另外一台机器上 数据解压缩 校验正确性 这样做会很有效率,数据压缩后可以更有效的利用带宽 使用ZIP+SCP 我们可以通过ZIP+SCP的组合实现这个功能。

这条命令是将/home/yankay/data经过GZIP压缩,通过ssh传输到yankay01的机器上。 data文件的大小是1.1GB,经过Zip压缩后是183MB,执行上面的命令需要45.6s。平均吞吐量为24.7MB/s 我们会发现Scp也有压缩功能,所以上面的语句可以写成

这样运行效果是相同的,不通之处在于我使用了blowfish算法作为Scp的密匙算法,使用这个算法可以比默认的情况快很多。单单对与scp,使用了blowfish 吞吐量是62MB/s,不使用只有46MB/s。 可是我执行上面一条命令的时候,发现还是需要45s。平均吞吐量还为24MB/s。没有丝毫的提升,可见瓶颈不在网络上。 那瓶颈在哪里呢? 性能分析 我们先定义几个变量 压缩工具的压缩比是 CompressRadio 压缩工具的压缩吞吐是CompressSpeed MB/s 网络传输的吞吐是 NetSpeed MB/s 由于使用了管道,管道的性能取决于管道中最慢的部分的性能,所以整体的性能是: speed=min(NetSpeed/CompressRadio,CompressSpeed) 当压缩吞吐较网络传输慢的时候,压缩是瓶颈;但网络较慢的时候,网络传输/吞吐 是瓶颈。 根据现有的测试数据(纯文本),可以得到表格: 压缩比 吞吐量 千兆网卡(100MB/s)吞吐量 千兆网卡吞吐量,基于ssh(62MB/s) 百兆网卡(10MB/s)吞吐量 ZLIB 35.80%…

Linux下常用的文件传输方式介绍与比较

本文介绍了linux之间传输文件的几种方式,并通过具体实验测试了几种文件传输方式之间的传输速度。这篇文章是我一次作业的实验报告,我经常查看这个文档,所以贴出来方便自己查略。 0. 实验环境以及实验数据 实验环境: 两台装有Ubuntu的电脑,两台电脑位于同一个局域网中,传输速度约4.1MB/s。 实验数据: 使用MySQL的日志文件(ib_logfile0)进行测试,日志文件压缩前1.1G,压缩后159M,具体应用中,压缩比例可能没有这么高,但是不影响我们的讨论。 1. scp scp是secure copy的缩写,scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令,主要用于linux服务器之间复制文件和目录。scp使用ssh安全协议传输数据,具有和ssh一样的验证机制,从而可以实现安全的远程拷贝文件。 下面介绍SCP三种不同用法的效率。注意:使用SCP前请配制好SSH。 1.1 scp 不使用压缩 将本地文件拷贝到远程服务器:

将远程服务器中的文件拷贝到本地的用法:

经测试,SCP不启用压缩功能的情况下,传输ib_logfile0文件需要4:12s。 1.2 压缩后传输 SCP传输ib_logfile0文件之所以需要那么多时间,是因为它没有对传输的数据进行压缩,可以先 将文件压缩,然后再进行远程拷贝。如下所示:

经测试,先手动压缩,然后再传输,4次测试结果的平均值为00:39s。 1.3 scp启用压缩 相对于第一种方法,第二种方法极大地减少了传输时间,但是需要执行三条语句,较为麻烦。更简单的方法如下所示:

-C选项启用了SSH的压缩功能,通过man ssh可以看到,在-C选项的解释部分有这么一句话:”the compression algorithm is the same used by gzip”。SSH与gzip使用的是同一种压缩算法,即第二种方法与第三种方法几乎一样,但是,第三种方法更为简单方便,所以,推荐使用第三种方法传输数据。…

将Linux命令的结果作为下一个命令的参数

1. 符号: 名称:反引号,上分隔符 位置:反引号()这个字符一般在键盘的左上角,数字1的左边,不要将其同单引号(’)混淆 作用:反引号括起来的字符串被shell解释为命令行,在执行时,shell首先执行该命令行,并以它的标准输出结果取代整个反引号(包括两个反引号)部分 举例:

2. $()  效果同 3. 命令:xargs xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。它把一个数据流分割为一些足够小的块,以方便过滤器和命令进行处理。通常情况下,xargs从管道或者stdin中读取数据,但是它也能够从文件的输出中读取数据。xargs的默认命令是echo,这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。

管道与xargs的区别: 管道是实现“将前面的标准输出作为后面的标准输入” xargs是实现“将标准输入作为命令的参数” 4. find命令的-exec参数 xargs:通过缓冲方式并以前面命令行的输出作为参数,随后的命令调用该参数 若忽略 xargs 的 options 来看的话, cm1 | xargs cm2 可以单纯看成: cm2 cm1 因此, find …. | xargs rm 也可作 rm…

查找Linux进程目录

Linux下我们一般使用ps查看进程信息,但是ps给出的进程信息比较有限,没有进程的工作路径,进程命令的绝对路径等等,这时候我们可以通过Linux下 /proc/ 目录下存储的信息进行查询进程命令路径信息。 Linux下,任何一个程序启动以后,系统会为其分配一个ID,即我们熟悉的PID,称为进程号,与此同时,系统会在/proc目录下为其创建一个独立的文件夹,文件夹以PID命名,在该文件夹内保存着该进程运行相关的详细信息,有兴趣的朋友可以进到这个目录下好好研究研究,不过今天的重点是获得该进程的绝对路径。 在 /proc/ 该目录下有一个名为exe的文件,像Windows系统下的可执行文件,这其实是一个符号链接(类似于Windows下的快捷方式),它指向该进程对应程序的绝对路径。用file命令或ls命令查看该符号链接的属性即可获取它所指向的绝对路径:

将上面命令中的PID换成你要查询的Linux进程号就可以。

加速Linux程序编译

项目越来越大,每次需要重新编译整个项目都是一件很浪费时间的事情。Research了一下,找到以下可以帮助提高速度的方法,总结一下。 1. tmpfs 有人说在Windows下用了RAMDisk把一个项目编译时间从4.5小时减少到了5分钟,也许这个数字是有点夸张了,不过粗想想,把文件放到内存上做编译应该是比在磁盘上快多了吧,尤其如果编译器需要生成很多临时文件的话。 这个做法的实现成本最低,在Linux中,直接mount一个tmpfs就可以了。而且对所编译的工程没有任何要求,也不用改动编译环境。 mount –t tmpfs tmpfs ~/build –o size=1G 用2.6.32.2的Linux Kernel来测试一下编译速度: 用物理磁盘:40分16秒 用tmpfs:39分56秒 呃……没什么变化。看来编译慢很大程度上瓶颈并不在IO上面。但对于一个实际项目来说,编译过程中可能还会有打包等IO密集的操作,所以只要可能,用tmpfs是有益无害的。当然对于大项目来说,你需要有足够的内存才能负担得起这个tmpfs的开销。 make -j 既然IO不是瓶颈,那CPU就应该是一个影响编译速度的重要因素了。 用make -j带一个参数,可以把项目在进行并行编译,比如在一台双核的机器上,完全可以用make -j4,让make最多允许4个编译命令同时执行,这样可以更有效的利用CPU资源。 还是用Kernel来测试: 用make: 40分16秒 用make -j4:23分16秒 用make -j8:22分59秒 由此看来,在多核CPU上,适当的进行并行编译还是可以明显提高编译速度的。但并行的任务不宜太多,一般是以CPU的核心数目的两倍为宜。 不过这个方案不是完全没有cost的,如果项目的Makefile不规范,没有正确的设置好依赖关系,并行编译的结果就是编译不能正常进行。如果依赖关系设置过于保守,则可能本身编译的可并行度就下降了,也不能取得最佳的效果。 ccache ccache用于把编译的中间结果进行缓存,以便在再次编译的时候可以节省时间。这对于玩Kernel来说实在是再好不过了,因为经常需要修改一些Kernel的代码,然后再重新编译,而这两次编译大部分东西可能都没有发生变化。对于平时开发项目来说,也是一样。为什么不是直接用make所支持的增量编译呢?还是因为现实中,因为Makefile的不规范,很可能这种“聪明”的方案根本不能正常工作,只有每次make clean再make才行。 安装完ccache后,可以在/usr/local/bin下建立gcc,g++,c++,cc的symbolic link,链到/usr/bin/ccache上。总之确认系统在调用gcc等命令时会调用到ccache就可以了(通常情况下/usr/local/bin会在PATH中排在/usr/bin前面)。 继续测试: 用ccache的第一次编译(make -j4):23分38秒…

linux下批量替换文件内容的三种办法

程序开发中,可能你会经常遇到批量替换文件内容的情况,如果你使用的是linux,那么恭喜你,你可以使用一下三种办法进行查找替换。 方法一:

这里使用了perl语言,使用-e加上一段代码,从而批量地将当前目录及所有子目录下的file.log文件中的string1替换成了string2 string支持正则表达式 方法二:

这里使用了sed命令,将/path目录及其子目录下的所有文件中的string1替换成了string2 这个命令,可能对返回多个文件不太支持,不太推荐! 方法三:

这里使用了shell命令,先查找出文件,再用awk分割(以:切分),再行替换! 注意: grep可以使用正则,也可以使用\转义一些特殊字符,比如”等

如何查看linux硬件配置信息

1.查看机器所有硬件信息: dmidecode |more dmesg |more 这2个命令出来的信息都非常多,所以建议后面使用”|more”便于查看 2.查看CPU信息 方法一: Linux下CPU相关的参数保存在 /proc/cpuinfo 文件里 cat /proc/cpuinfo |more 方法二: 采用命令 dmesg | grep CPU 可以查看到相关CPU的启动信息 查看CPU的位数: getconf LONG_BIT 3.查看Mem信息 cat /proc/meminfo |more (注意输出信息的最后一行:MachineMem:   41932272 kB) free -m top 4.查看磁盘信息 方法一: fdisk -l 可以看到系统上的磁盘(包括U盘)的分区以及大小相关信息。 方法二: 直接查看 cat /proc/partitions 5.查看网卡信息…

Page 1 of 212