• Linux系统strac命令


    strace :监控程序的执行状况
    在linux 空间下,运行一个程序时,操作系统会将应用程序封装一个进程的形式,参与操作系统的调度,可以使用strace 跟踪程序运行的情况。
     
    基本功能
    监控用户进程与内核进程的交互
    追踪进程的系统调用、信号传递、状态变化
    一、系统调用
    分类
    文件和设备访问:open、close、read、write、ioctl等
    进程管理:fork、clone、execve、exit 等
    信号:signal、kill等
    内存管理:brk、mmap、mlock等
    进程间通信:semget、信号量、消息队列
    网络通信:socket、connect等
    常用参数
    -c 统计每一系统调用的所执行的时间,次数和出错的次数等
    -d 输出strace关于标准错误的调试信息
    -f 跟踪由目标进程及调用所产生的子进程
    -F 尝试跟踪目标调用 在-f时,vfork不被跟踪
    -a 设置返回值的输出位置.默认 为40
    -r 打印出相对时间关于每一个系统调用
    -t 在每行输出的后面,显示调用花费时间
    -tt 在每行输出的前面,显示调用花费毫秒级别的时间
    -T 每次系统调用所花费的时间
    -v 对某些相关调用,把完整的环境变量、文件stat结构打印出来
    -p pid 指定要跟踪的进程pid,同时跟踪的多个pid,重复多次-p选项即可
    -o filename: 将跟踪输出写入文件名
    -s 当系统调用的某个参数是字符串时,最多输出制定长度的内容,默认时32个字节 
     
    -e set: 仅跟踪某些系统调用
    -e open,close: 仅跟踪打开/关闭系统调用
    -e file: 仅跟踪文件系统调用/文件操作相关的
    -e process: 跟踪所有涉及流程管理的系统调用
    -e network: 跟踪所有与网络相关的系统调用
    -e signal:跟踪所有与信号相关的系统调用
    -e ipc: 跟踪所有与ipc相关的系统调用
    -e desc: 跟踪所有与文件描述符相关的系统调用
    -e memory: 跟踪所有与内存映射相关的系统调用
    -e set: 仅跟踪指定的信号子集
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    示例《一》
    查看一个程序所有的open、close系统调用
    查看每个程序调用消耗的时间
    统计系统调用次数、错误次数统计
    打印系统调用的时间戳
    将追踪日志保存到log文件中
    注释:
     
     查看所有程序运行 strace python server.py
     查看所有程序运行 strace ./aa.sh
     
     查看打开系统调用情况 strace -e open ./aa.sh
     查看打开关闭系统调用情况 strace -e open,close ./aa.sh
     查看打开关闭系统调用时间 strace -T -e open,close python3 main.py (T 时间在后面显示)
     
     查看打开关闭系统调用次数 strace -c -T -e open,close ./aa.sh (如程序一直在运行,停止后才会统计)
     查看打开关闭系统调用时间 strace -t -T -e open,close ./aa.sh  
     查看打开关闭系统调用时间 strace -tt -T -e open,close ./aa.sh (tt 
     查看打开系统调用输入log strace -tt -T -e open -o trace.log ./aa.sh (-o 输入trace.log文件)
     
    strace -tt -T -V -e trace=file -o /data/log/trace.log -s 1024 -p 23489
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    二、系统调用函数说明
    进程管理
     
    函数名 说明
    fork 创建一个新进程
    clone 按制定条件创建子进程
    execve 运行可执行文件
    pause 进程将处于阻塞状态
    wait 等待子进程终止
    waitpid 等待制定子进程终止
    文件和设备访问
     
    函数名 说明
    open 打开文件
    create 创建新文件
    close 关闭文件描述符
    read 读文件
    write 写文件
    pread 对文件随机读
    pwrite 对文件随机写
    poll I/o多路转换
    truncate 截断文件
    文件系统操作
     
    函数名 说明
    access 确定文件的可存取性
    chmod 确定文件的可存取性
    chown 改变文件的属主或用户组
    chroot 改变文件状态信息
    stat 获取文件的状态信息
    lstat 获取文件的状态信息
    getdents 读取目录项
    mkdir 创建目录
    link 建立链接
    内存管理
     
    函数名 说明
    mmap 映射虚拟内存页(分配内存)
    sync 将内存缓冲区数据写回硬盘
    socket 控制
     
    函数名 说明
    socketcall socket系统调用
    socket 建立socket
    bind 绑定socket到端口
    connect 链接远程主机
    send 通过socket发送信息
    sendto 发送UDP信息
    sendmsg 参见send
    listen 监听socket端口
    select 对多路同步I/O进行轮询
    示例《二》
    ping baidu系统调用过程
     
    ping www.baidu.com
    strace ping www.baidu.com
    strace -e poll,select,connect,sendto ping www.baidu.com
    1
    2
    3
    1
    2
    3
    cat /etc/passwd 系统调用过程
     
    strace cat /etc/passwd
    1
    1
    [root@VM-0-14-centos ~]# strace cat /etc/passwd
     
    运行命令
    execve("/usr/bin/cat", ["cat", "/etc/passwd"], 0x7ffeee8bfe78 /* 28 vars */) = 0
    brk(NULL) = 0x1d9f000
     
    为运行命名分配内存空间
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6081756000
     
    确定文件的可存取性 -1 表示文件不可读
    access("/etc/ld.so.preload", R_OK) = -1 ENOENT (没有那个文件或目录)
     
    打开文件 
    open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
     
    文件状态:作用于已打开的文件的文件描述符而不是文件名
    fstat(3, {st_mode=S_IFREG|0644, st_size=37645, ...}) = 0
    mmap(NULL, 37645, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f608174c000
    close(3) = 0
    open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
     
    读取文件
    read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`&\2\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=2156352, ...}) = 0
    mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6081168000
     
    参见下文mprotect 命令
    mprotect(0x7f608132c000, 2093056, PROT_NONE) = 0
    mmap(0x7f608152b000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f608152b000
    mmap(0x7f6081531000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f6081531000
    close(3) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f608174b000
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6081749000
    arch_prctl(ARCH_SET_FS, 0x7f6081749740) = 0
    mprotect(0x7f608152b000, 16384, PROT_READ) = 0
    mprotect(0x60b000, 4096, PROT_READ) = 0
    mprotect(0x7f6081757000, 4096, PROT_READ) = 0
    munmap(0x7f608174c000, 37645) = 0
    brk(NULL) = 0x1d9f000
    brk(0x1dc0000) = 0x1dc0000
    brk(NULL) = 0x1dc0000
    open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=106176928, ...}) = 0
    mmap(NULL, 106176928, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f607ac25000
    close(3) = 0
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
    open("/etc/passwd", O_RDONLY) = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=1419, ...}) = 0
    fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
    read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 65536) = 1419
    write(1, "root:x:0:0:root:/root:/bin/bash\n"..., 1419root:x:0:0:root:
     
     
    在Linux中,mprotect()函数可以用来修改一段指定内存区域的保护属性。
    函数原型如下:
     
    #include <unistd.h>
    #include <sys/mmap.h>
    int mprotect(const void *start, size_t len, int prot);
    mprotect()
    函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
     
    prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:
    1)PROT_READ:表示内存段内的内容可写;
    2)PROT_WRITE:表示内存段内的内容可读;
    3)PROT_EXEC:表示内存段中的内容可执行;
    4)PROT_NONE:表示内存段中的内容根本没法访问。
    其他:
    需要指出的是,指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必须是页大小的整数倍。
  • 相关阅读:
    Ubuntu自启动服务脚本
    坑(一)—— Django ORM 连接超时的坑
    logging模块详解
    端口扫描之nmap命令
    端口扫描之masscan扫描
    端口扫描之Scapy模块的使用
    端口扫描之开放端口扫描方式
    Android Studio导入Project、Module的正确方法
    ImportError: No module named 'requests'
    运行python程序
  • 原文地址:https://www.cnblogs.com/nizuimeiabc1/p/16740578.html
Copyright © 2020-2023  润新知