本章和考试完全无关,老师讲strace的目的可以简单理解成帮助我们提升技术视野,篇幅不长,可略读
strace是什么?
看了定义大概能猜到叭:其作用是Debug和分析应用程序!!!
strace有什么功能?
现在明确了,其就是用来分析应用程序或者Debug的,比如程序运行很慢,那可以统计下程序在执行过程中有多少次和IO相关的系统调用,如果某一个功能运行时IO相关的系统调用明显变多,那么IO得背锅了!
下面动手写代码,很简单的代码:
#include
#include
#include
char *s[10]={"cat", "pi1.c", NULL};
int main(){
execvp("cat", s);
exit(0);
}
然后编译:gcc -o test test.c
然后:strace ./test 2> log.txt 将strace给出的系统调用信息重定向到log.txt中,看内容,有点多:
execve("./test", ["./test"], [/* 72 vars */]) = 0
brk(NULL) = 0x9c8e000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f21000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=86603, ...}) = 0
mmap2(NULL, 86603, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f0b000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\207\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1786484, ...}) = 0
mmap2(NULL, 1792540, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7d55000
mmap2(0xb7f05000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1af000) = 0xb7f05000
mmap2(0xb7f08000, 10780, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f08000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7d54000
set_thread_area({entry_number:-1, base_addr:0xb7d54700, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb7f05000, 8192, PROT_READ) = 0
mprotect(0x8049000, 4096, PROT_READ) = 0
mprotect(0xb7f4a000, 4096, PROT_READ) = 0
munmap(0xb7f0b000, 86603) = 0
execve("/home/zjp/bin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve("/home/zjp/.local/bin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/local/sbin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/local/bin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/sbin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/bin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve("/sbin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve("/bin/cat", ["cat", "pi1.c"], [/* 72 vars */]) = 0
brk(NULL) = 0x9507000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f44000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=86603, ...}) = 0
mmap2(NULL, 86603, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f2e000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\207\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1786484, ...}) = 0
mmap2(NULL, 1792540, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7d78000
mmap2(0xb7f28000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1af000) = 0xb7f28000
mmap2(0xb7f2b000, 10780, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f2b000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7d77000
set_thread_area({entry_number:-1, base_addr:0xb7d77700, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb7f28000, 8192, PROT_READ) = 0
mprotect(0x8054000, 4096, PROT_READ) = 0
mprotect(0xb7f6d000, 4096, PROT_READ) = 0
munmap(0xb7f2e000, 86603) = 0
brk(NULL) = 0x9507000
brk(0x9528000) = 0x9528000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=10219008, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7b77000
close(3) = 0
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=10219008, ...}) = 0
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0x741000) = 0xb7f43000
close(3) = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
open("pi1.c", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0664, st_size=713, ...}) = 0
fadvise64_64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
mmap2(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7b55000
read(3, "#include\n#include\n#include
好吧,我承认看不明白,太多了叭~!也就最后几行看的直观点!
直接在命令行敲入:sudo strace dd if=/dev/zero of=/dev/null 2> log.txt
仍然能得到一大堆的信息,不过大量出现read(…),这属于IO密集型应用
我们刚才的运行方式是strace ./test,那么如果某一个进程已经在运行了,我想用strace跟踪其系统调用怎么办?
首先top指令找到该进程的id号,然后sudo strace -p 4375,就OK了!!!
很简单-c选项,count=xxx,表示统计多少次,如上图所示能给出比较详细的统计信息,至于上述信息什么意思暂且不深究,这里大概理解strace命令能统计应用程序的系统调用即可,未来可能用得到!!!
我们主要研究fread 和 read 的区别
fwrite和write的区别。
之前讲过缓存思想在计算机发展史上是十分伟大的,同理fread和fwrite也是利用缓存的思想。
我们在用c语言的fread和fwrite的时候,需要使用FILE结构体,该结构体内部维护了一个缓冲区。
在读取操作时:先调用read系统调用将内部缓冲区填满,然后从内部缓冲区读数据,同理再次调用fread的时候,可以先判断相关数据是否在缓冲区内,如果在那么就不用调用read系统调用了,下面我们实验验证,这个实验做的可能有点小问题:
代码:
#include
int main(){
FILE *fp;
char buf[1024];
int i;
fp=fopen("pi1.c", "r");
for(i=0; i<1024; i++){
fread(buf, 1, 1, fp);
}
}
编译运行strace ./test_fread,结果如下
按照我的理解,read应该只调用一次鸭?为什么调用了那么多,不过有点靠谱的一点是:只有第一个read真正读取到了数据,其他的read都没有读取到数据,因为返回值表示读取到的字节数!
使用strace还可以做什么呢?
//代码大概时这个样子
strace lua thread.lua 2>&1 | grep clone
strace python thread.py 2>&1 | grep clone
Linux的多线程基于clone系统调用,Linux中的线程只是在被创建时clone了父进程的资源。
本章和考试几乎无关,fread和read以及fwrite和write的区别可能会考!
本系列博客目录
下一篇:IO