Strace muLinux: nhoroondo, dhizaini uye kushandiswa

Strace muLinux: nhoroondo, dhizaini uye kushandiswa

MuUnix-senge masisitimu ekushandisa, kutaurirana kwechirongwa nenyika yekunze uye sisitimu yekushandisa inoitika kuburikidza nechikamu chidiki chemabasa - system call. Izvi zvinoreva kuti nezvinangwa zvekugadzirisa zvinogona kubatsira kufeya nharembozha dziri kuitwa nemaitiro.

Chishandiso chinokubatsira kutarisa "hupenyu hwepedyo" hwezvirongwa paLinux strace, iyo iri musoro wenyaya ino. Mienzaniso yekushandiswa kwemidziyo yevasori inoperekedzwa nenhoroondo pfupi strace uye tsanangudzo yekugadzirwa kwezvirongwa zvakadaro.

Zviri mukati

Kwakatangira mhando

Iyo huru interface pakati pezvirongwa uye OS kernel muUnix ndeye system mafoni. system inofona, syscalls), kupindirana kwezvirongwa nenyika yekunze kunoitika chete kuburikidza navo.

Asi mune yekutanga vhezheni yeruzhinji yeUnix (Version 6 Unix, 1975) pakanga pasina nzira dziri nyore dzekutevera maitiro evashandisi maitiro. Kugadzirisa nyaya iyi, Bell Labs ichagadziridza kune inotevera vhezheni (Version 7 Unix, 1979) vakakurudzira kufona kwehurongwa hutsva - ptrace.

ptrace yakagadziridzwa zvakanyanya kune inodyidzana debugger, asi pakupera kwema80s (munguva yekutengeserana. System V Kuburitswa 4) pahwaro uhwu, zvigadziriso zvisina kunangidzira ngwariroβ€”system call tracersβ€”zvakaonekwa uye zvakava kushandiswa zvikuru.

Kutanga the same version of strace yakabudiswa naPaul Cronenburg pane comp.sources.sun mailing list muna 1992 seimwe nzira kune yakavharwa utility. trace kubva kuZuva. Ose ari maviri clone uye ekutanga akaitirwa SunOS, asi ne1994 strace yakaendeswa kuSystem V, Solaris uye Linux iri kuramba ichizivikanwa.

Nhasi strace inongotsigira Linux uye inovimba zvakafanana ptrace, yakakuriswa nekuwedzera kwakawanda.

Yemazuva ano (uye inoshanda kwazvo) muchengeti strace - Dmitry Levin. Kutenda kwaari, chishandiso chakawana zvepamberi senge jekiseni rekukanganisa munharembozha, tsigiro yeakasiyana ezvivakwa uye, zvakanyanya kukosha, mascot. Zvinyorwa zvisiri pamutemo zvinoti sarudzo yakawira mhou nekuda kwekuwirirana pakati pezwi rechiRussian rekuti "mhou" uye izwi rechirungu "strace".

Izvo zvakakoshawo kuti ptrace system call uye tracers hazvina kumbobvira zvakabatanidzwa muPOSIX, kunyangwe nhoroondo refu uye kuita muLinux, FreeBSD, OpenBSD uye yechinyakare Unix.

Strace mudziyo muchidimbu: Piglet Trace

"Hautarisirwe kuti unzwisise izvi" (Dennis Ritchie, chirevo muVersion 6 Unix source code)

Kubvira pauduku, handigoni kumira mabhokisi madema: handina kutamba nematoyi, asi ndakaedza kunzwisisa maitiro avo (vakuru vakashandisa shoko rokuti "kuputsika," asi musatenda mitauro yakaipa). Zvichida ichi ndicho chikonzero tsika isina kurongeka yekutanga Unix uye yemazuva ano yakavhurika-sosi kufamba iri padyo neni.

Nezvinangwa zvechinyorwa ichi, hazvina musoro kuparadzanisa iyo kodhi kodhi yestrace, iyo yakakura kwemakumi emakore. Asi hapafaniri kuva nezvakavanzika zvinosiiwa kuvaverengi. Naizvozvo, kuratidza musimboti wekushanda kweakadaro strace zvirongwa, ini ndichapa iyo kodhi ye miniature tracer - Piglet Trace (ptr). Iyo haizive kuita chero chinhu chakakosha, asi chinhu chikuru ndeye system inofona yechirongwa - inoburitsa:

$ gcc examples/piglet-trace.c -o ptr
$ ptr echo test > /dev/null
BRK(12) -> 94744690540544
ACCESS(21) -> 18446744073709551614
ACCESS(21) -> 18446744073709551614
unknown(257) -> 3
FSTAT(5) -> 0
MMAP(9) -> 140694657216512
CLOSE(3) -> 0
ACCESS(21) -> 18446744073709551614
unknown(257) -> 3
READ(0) -> 832
FSTAT(5) -> 0
MMAP(9) -> 140694657208320
MMAP(9) -> 140694650953728
MPROTECT(10) -> 0
MMAP(9) -> 140694655045632
MMAP(9) -> 140694655070208
CLOSE(3) -> 0
unknown(158) -> 0
MPROTECT(10) -> 0
MPROTECT(10) -> 0
MPROTECT(10) -> 0
MUNMAP(11) -> 0
BRK(12) -> 94744690540544
BRK(12) -> 94744690675712
unknown(257) -> 3
FSTAT(5) -> 0
MMAP(9) -> 140694646390784
CLOSE(3) -> 0
FSTAT(5) -> 0
IOCTL(16) -> 18446744073709551591
WRITE(1) -> 5
CLOSE(3) -> 0
CLOSE(3) -> 0
unknown(231)
Tracee terminated

Piglet Trace inoziva nezve mazana eLinux system mafoni (ona. tafura) uye inoshanda chete pa x86-64 architecture. Izvi zvakakwana nokuda kwezvinangwa zvekudzidzisa.

Ngatitarisei basa re clone yedu. Munyaya yeLinux, debuggers uye tracers vanoshandisa, sezvataurwa pamusoro, iyo ptrace system call. Inoshanda nekupfuura munharo yekutanga zviziviso zvemirairo, izvo zvatinoda chete PTRACE_TRACEME, PTRACE_SYSCALL ΠΈ PTRACE_GETREGS.

Iyo tracer inotanga mune yakajairwa Unix maitiro: fork(2) inotanga nzira yemwana, iyo inoshandisawo exec(3) inotanga chirongwa chiri kudzidza. Kusachenjera chete apa ndiko kunetsa ptrace(PTRACE_TRACEME) ΠΏΠ΅Ρ€Π΅Π΄ exec: Maitiro emwana anotarisira maitiro emubereki kuti atarise:

pid_t child_pid = fork();
switch (child_pid) {
case -1:
    err(EXIT_FAILURE, "fork");
case 0:
    /* Child here */
    /* A traced mode has to be enabled. A parent will have to wait(2) for it
     * to happen. */
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
    /* Replace itself with a program to be run. */
    execvp(argv[1], argv + 1);
    err(EXIT_FAILURE, "exec");
}

Maitiro evabereki anofanira ikozvino kufona wait(2) mukuita kwemwana, kureva kuti, ita shuwa kuti switching to trace mode yaitika:

/* Parent */

/* First we wait for the child to set the traced mode (see
 * ptrace(PTRACE_TRACEME) above) */
if (waitpid(child_pid, NULL, 0) == -1)
    err(EXIT_FAILURE, "traceme -> waitpid");

Panguva ino, gadziriro dzakwana uye iwe unogona kuenderera wakananga ku tracking system mafoni mune isingaperi loop.

Dambudziko ptrace(PTRACE_SYSCALL) inovimbisa izvo zvinotevera wait mubereki anopedzisa kungave kusati kwaitwa kufona system kana nekukurumidza kana yapera. Pakati pemafona maviri unogona kuita chero zviito: tsiva kufona neimwe imwe, shandura nharo kana kukosha kwekudzoka.

Tinongoda kudana murairo kaviri ptrace(PTRACE_GETREGS)kuti uwane registry state rax pamberi pekufona (nhamba yekufona system) uye nekukurumidza mushure (kudzosa kukosha).

Chaizvoizvo, kutenderera:

/* A system call tracing loop, one interation per call. */
for (;;) {
    /* A non-portable structure defined for ptrace/GDB/strace usage mostly.
     * It allows to conveniently dump and access register state using
     * ptrace. */
    struct user_regs_struct registers;

    /* Enter syscall: continue execution until the next system call
     * beginning. Stop right before syscall.
     *
     * It's possible to change the system call number, system call
     * arguments, return value or even avoid executing the system call
     * completely. */
  if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
      err(EXIT_FAILURE, "enter_syscall");
  if (waitpid(child_pid, NULL, 0) == -1)
      err(EXIT_FAILURE, "enter_syscall -> waitpid");

  /* According to the x86-64 system call convention on Linux (see man 2
   * syscall) the number identifying a syscall should be put into the rax
   * general purpose register, with the rest of the arguments residing in
   * other general purpose registers (rdi,rsi, rdx, r10, r8, r9). */
  if (ptrace(PTRACE_GETREGS, child_pid, NULL, &registers) == -1)
      err(EXIT_FAILURE, "enter_syscall -> getregs");

  /* Note how orig_rax is used here. That's because on x86-64 rax is used
   * both for executing a syscall, and returning a value from it. To
   * differentiate between the cases both rax and orig_rax are updated on
   * syscall entry/exit, and only rax is updated on exit. */
  print_syscall_enter(registers.orig_rax);

  /* Exit syscall: execute of the syscall, and stop on system
   * call exit.
   *
   * More system call tinkering possible: change the return value, record
   * time it took to finish the system call, etc. */
  if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
      err(EXIT_FAILURE, "exit_syscall");
  if (waitpid(child_pid, NULL, 0) == -1)
      err(EXIT_FAILURE, "exit_syscall -> waitpid");

  /* Retrieve register state again as we want to inspect system call
   * return value. */
  if (ptrace(PTRACE_GETREGS, child_pid, NULL, &registers) == -1) {
      /* ESRCH is returned when a child terminates using a syscall and no
       * return value is possible, e.g. as a result of exit(2). */
      if (errno == ESRCH) {
          fprintf(stderr, "nTracee terminatedn");
          break;
      }
      err(EXIT_FAILURE, "exit_syscall -> getregs");
  }

  /* Done with this system call, let the next iteration handle the next
   * one */
  print_syscall_exit(registers.rax);
}

Ndiyo tracer yese. Zvino iwe unoziva pekutangira kunotevera porting DTrace paLinux.

Basics: kumhanya chirongwa chinomhanya tambo

Sekutanga kushandiswa strace, pamwe zvakakodzera kutaura nzira iri nyore - kutanga application inoshanda strace.

Kuti usapinda mune isingaperi runyorwa rwekufona kwechirongwa chakajairika, tinonyora purogiramu shoma kumativi ose write:

int main(int argc, char *argv[])
{
    char str[] = "write me to stdoutn";
    /* write(2) is a simple wrapper around a syscall so it should be easy to
     * find in the syscall trace. */
    if (sizeof(str) != write(STDOUT_FILENO, str, sizeof(str))){
        perror("write");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

Ngativakei purogiramu uye tive nechokwadi chokuti inoshanda:

$ gcc examples/write-simple.c -o write-simple
$ ./write-simple
write me to stdout

Uye pakupedzisira, ngatimhanyei pasi pe strace control:

$ strace ./write-simple
pexecve("./write", ["./write"], 0x7ffebd6145b0 /* 71 vars */) = 0
brk(NULL)                               = 0x55ff5489e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=197410, ...}) = 0
mmap(NULL, 197410, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7a2a633000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF21133>1260342"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7a2a631000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7a2a04c000
mprotect(0x7f7a2a233000, 2097152, PROT_NONE) = 0
mmap(0x7f7a2a433000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f7a2a433000
mmap(0x7f7a2a439000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7a2a439000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f7a2a6324c0) = 0
mprotect(0x7f7a2a433000, 16384, PROT_READ) = 0
mprotect(0x55ff52b52000, 4096, PROT_READ) = 0
mprotect(0x7f7a2a664000, 4096, PROT_READ) = 0
munmap(0x7f7a2a633000, 197410)          = 0
write(1, "write me to stdoutn", 20write me to stdout
)  = 20
exit_group(0)                           = ?

Zvakanyanya "mazwi" uye kwete zvakanyanya kudzidzisa. Pane matambudziko maviri pano: chirongwa chinobuda chinosanganiswa nezvakabuda strace uye kuwanda kwenharembozha dzisingatifarire.

Iwe unogona kupatsanura chirongwa cheyakajairwa kubuda rwizi uye strace kukanganisa kubuda uchishandisa -o switch, iyo inodzoreredza rondedzero yehurongwa hwekufona kune faira rekupokana.

Inoramba ichitarisana nedambudziko re "extra" call. Ngatifungei kuti isu tiri kungofarira kufona write. Key -e inokutendera kuti utaure mataurirwo ayo masystem achasefa. Iyo inonyanya kufarirwa mamiriro sarudzo ndeye, zvakasikwa, trace=*, iyo yaunogona kusiya chete mafoni anotifarira.

Kana yakashandiswa panguva imwe chete -o ΠΈ -e tichawana:

$ strace -e trace=write -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
write(1, "write me to stdoutn", 20
)  = 20
+++ exited with 0 +++

Saka, munoona, zviri nyore kuverenga.

Iwe unogona zvakare kubvisa masisitimu mafoni, semuenzaniso ane hukama nekugovaniswa uye kusunungura:

$ strace -e trace=!brk,mmap,mprotect,munmap -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
execve("./write-simple", ["./write-simple"], 0x7ffe9972a498 /* 69 vars */) = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=124066, ...}) = 0
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF21133>1260342"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f00f0be74c0) = 0
write(1, "write me to stdoutn", 20)  = 20
exit_group(0)                           = ?
+++ exited with 0 +++

Ziva mucherechedzo wakapunyuka mune rondedzero yekusabatanidzwa mafoni: izvi zvinodikanwa negomba rekuraira. deko).

Mune yangu vhezheni ye glibc, kufona system kunopedza maitiro exit_group, kwete zvechivanhu _exit. Uku ndiko kuoma kwekushanda nehurongwa hwekufona: iyo interface iyo iyo programmer inoshanda haina hukama zvakananga nehurongwa hwekufona. Uyezve, inochinja nguva dzose zvichienderana nekushandiswa uye chikuva.

Basics: kujoinha maitiro pane nhunzi

Pakutanga, iyo ptrace system inodaidza payakavakirwa strace, inogona kushandiswa chete paunenge uchimhanyisa chirongwa mune yakakosha modhi. Kuganhurirwa uku kungave kwakanzwika kuva kune musoro mumazuva eVersion 6 Unix. Mazuva ano, izvi hazvisisina kukwana: dzimwe nguva unoda kuongorora matambudziko epurogiramu yekushanda. Muenzaniso wakajairika inzira yakavharwa pamubato kana kurara. Saka mazuvano strace inogona kujoinha maitiro pakubhururuka.

Muenzaniso wechando zvirongwa:

int main(int argc, char *argv[])
{
    (void) argc; (void) argv;

    char str[] = "write men";

    write(STDOUT_FILENO, str, sizeof(str));

    /* Sleep indefinitely or until a signal arrives */
    pause();

    write(STDOUT_FILENO, str, sizeof(str));

    return EXIT_SUCCESS;
}

Ngativakei purogiramu uye tive nechokwadi chokuti yakaomeswa nechando:

$ gcc examples/write-sleep.c -o write-sleep
$ ./write-sleep
./write-sleep
write me
^C
$

Zvino ngatiedzei kuijoinha:

$ ./write-sleep &
[1] 15329
write me
$ strace -p 15329
strace: Process 15329 attached
pause(
^Cstrace: Process 15329 detached
 <detached ...>

Chirongwa chakavharwa nekufona pause. Ngationei kuti anoita sei kune zviratidzo:

$ strace -o write-sleep.log -p 15329 &
strace: Process 15329 attached
$
$ kill -CONT 15329
$ cat write-sleep.log
pause()                                 = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause(
$
$ kill -TERM 15329
$ cat write-sleep.log
pause()                                 = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause()                                 = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
+++ killed by SIGTERM +++

Takatanga chirongwa chechando ndokujoinha nacho tichishandisa strace. Zvinhu zviviri zvakave pachena: iyo yekumbomira system yekufona inofuratira masaini pasina mabati uye, zvinotofadza, strace monitors kwete chete system yekufona, asiwo masaini anouya.

Muenzaniso: Kuronda Maitiro Evana

Kushanda nematanho kuburikidza nekufona fork - hwaro hwese Unixes. Ngationei kuti strace inoshanda sei nemuti wekugadzira uchishandisa muenzaniso we "kubereka" kuri nyore. zvirongwa:

int main(int argc, char *argv[])
{
    pid_t parent_pid = getpid();
    pid_t child_pid = fork();
    if (child_pid == 0) {
        /* A child is born! */
        child_pid = getpid();

        /* In the end of the day printf is just a call to write(2). */
        printf("child (self=%d)n", child_pid);
        exit(EXIT_SUCCESS);
    }

    printf("parent (self=%d, child=%d)n", parent_pid, child_pid);

    wait(NULL);

    exit(EXIT_SUCCESS);
}

Pano maitiro ekutanga anogadzira maitiro emwana, ese achinyora kune yakajairwa kubuda:

$ gcc examples/fork-write.c -o fork-write
$ ./fork-write
parent (self=11274, child=11275)
child (self=11275)

Nekumisikidza, isu tinongoona masisitimu mafoni kubva kumaitiro evabereki:

$ strace -e trace=write -ofork-write.log ./fork-write
child (self=22049)
parent (self=22048, child=22049)
$ cat fork-write.log
write(1, "parent (self=22048, child=22049)"..., 33) = 33
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22049, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

Mureza unokubatsira kuti utarise iyo yose process tree -f, izvo strace monitors system call muma process emwana. Izvi zvinowedzera kumutsara wega wega wekubuda pid process inoita kuburitsa system:

$ strace -f -e trace=write -ofork-write.log ./fork-write
parent (self=22710, child=22711)
child (self=22711)
$ cat fork-write.log
22710 write(1, "parent (self=22710, child=22711)"..., 33) = 33
22711 write(1, "child (self=22711)n", 19) = 19
22711 +++ exited with 0 +++
22710 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22711, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
22710 +++ exited with 0 +++

Muchirevo chechinyorwa chino, kusefa neboka renharembozha kunogona kubatsira:

$ strace -f -e trace=%process -ofork-write.log ./fork-write
parent (self=23610, child=23611)
child (self=23611)
$ cat fork-write.log
23610 execve("./fork-write", ["./fork-write"], 0x7fff696ff720 /* 63 vars */) = 0
23610 arch_prctl(ARCH_SET_FS, 0x7f3d03ba44c0) = 0
23610 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f3d03ba4790) = 23611
23610 wait4(-1,  <unfinished ...>
23611 exit_group(0)                     = ?
23611 +++ exited with 0 +++
23610 <... wait4 resumed> NULL, 0, NULL) = 23611
23610 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=23611, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
23610 exit_group(0)                     = ?
23610 +++ exited with 0 +++

Nenzira, ndeipi system yekufona inoshandiswa kugadzira hurongwa hutsva?

Muenzaniso: mafaera nzira panzvimbo pezvibato

Kuziva mafaera anotsanangura kunobatsira, asi mazita emafaira anowanikwa nechirongwa anogonawo kuuya anobatsira.

Zvadaro chirongwa inonyora mutsetse kune faira renguva pfupi:

void do_write(int out_fd)
{
    char str[] = "write me to a filen";

    if (sizeof(str) != write(out_fd, str, sizeof(str))){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    char tmp_filename_template[] = "/tmp/output_fileXXXXXX";

    int out_fd = mkstemp(tmp_filename_template);
    if (out_fd == -1) {
        perror("mkstemp");
        exit(EXIT_FAILURE);
    }

    do_write(out_fd);

    return EXIT_SUCCESS;
}

Panguva yekufona yakajairika strace icharatidza kukosha kweiyo descriptor number yakapfuudzwa kune system call:

$ strace -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3, "write me to a filen", 20)  = 20
+++ exited with 0 +++

Nemureza -y Iyo inoshandiswa inoratidza nzira yefaira iyo inofananidzwa netsanangudzo:

$ strace -y -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3</tmp/output_fileCf5MyW>, "write me to a filen", 20) = 20
+++ exited with 0 +++

Muenzaniso: File Access Tracking

Chimwe chinhu chinobatsira: ratidza chete masisitimu mafoni ane chekuita nefaira chairo. Next chirongwa inoisa mutsara kune faira risinganzwisisike rakapfuudzwa senharo:

void do_write(int out_fd)
{
    char str[] = "write me to a filen";

    if (sizeof(str) != write(out_fd, str, sizeof(str))){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    /*
     * Path will be provided by the first program argument.
     *  */
    const char *path = argv[1];

    /*
     * Open an existing file for writing in append mode.
     *  */
    int out_fd = open(path, O_APPEND | O_WRONLY);
    if (out_fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    do_write(out_fd);

    return EXIT_SUCCESS;
}

kubudikidza default strace inoratidza ruzivo rwakawanda rusina basa. Flag -P ine nharo inokonzera strace kudhinda chete mafoni kune yakataurwa faira:

$ strace -y -P/tmp/test_file.log -o write-file.log ./write-file /tmp/test_file.log
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = 3</tmp/test_file.log>
write(3</tmp/test_file.log>, "write me to a filen", 20) = 20
+++ exited with 0 +++

Muenzaniso: Multithreaded Zvirongwa

Zvinobatsira strace inogonawo kubatsira kana uchishanda ne-multi-threaded purogiramu. Chirongwa chinotevera chinonyora kune yakajairwa kuburitsa kubva kuhova mbiri:

void *thread(void *arg)
{
    (void) arg;

    printf("Secondary thread: workingn");
    sleep(1);
    printf("Secondary thread: donen");

    return NULL;
}

int main(int argc, char *argv[])
{
    printf("Initial thread: launching a threadn");

    pthread_t thr;
    if (0 != pthread_create(&thr, NULL, thread, NULL)) {
        fprintf(stderr, "Initial thread: failed to create a thread");
        exit(EXIT_FAILURE);
    }

    printf("Initial thread: joining a threadn");
    if (0 != pthread_join(thr, NULL)) {
        fprintf(stderr, "Initial thread: failed to join a thread");
        exit(EXIT_FAILURE);
    };

    printf("Initial thread: done");

    exit(EXIT_SUCCESS);
}

Nomuzvarirwo, inofanirwa kuunganidzwa nekwaziso yakakosha kune linker - iyo -pthread mureza:

$ gcc examples/thread-write.c -pthread -o thread-write
$ ./thread-write
/thread-write
Initial thread: launching a thread
Initial thread: joining a thread
Secondary thread: working
Secondary thread: done
Initial thread: done
$

Flag -f, sezviri muchiitiko chemaitiro enguva dzose, ichawedzera pid yemaitiro kusvika pakutanga kwemutsara wega wega.

Nomuzvarirwo, hatisi kutaura nezve tambo identifier mupfungwa yekuitwa kwePOSIX Threads standard, asi nezve nhamba inoshandiswa nemugadziri webasa muLinux. Kubva pamaonero ekupedzisira, hapana maitiro kana tambo - kune mabasa anoda kugoverwa pakati peanowanikwa macores emuchina.

Paunenge uchishanda mune dzakawanda tambo, masisitimu mafoni anova akawandisa:

$ strace -f -othread-write.log ./thread-write
$ wc -l thread-write.log
60 thread-write.log

Zvine musoro kuzviganhurira iwe kugadzirisa manejimendi uye system inofona chete write:

$ strace -f -e trace="%process,write" -othread-write.log ./thread-write
$ cat thread-write.log
18211 execve("./thread-write", ["./thread-write"], 0x7ffc6b8d58f0 /* 64 vars */) = 0
18211 arch_prctl(ARCH_SET_FS, 0x7f38ea3b7740) = 0
18211 write(1, "Initial thread: launching a thre"..., 35) = 35
18211 clone(child_stack=0x7f38e9ba2fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f38e9ba39d0, tls=0x7f38e9ba3700, child_tidptr=0x7f38e9ba39d0) = 18212
18211 write(1, "Initial thread: joining a thread"..., 33) = 33
18212 write(1, "Secondary thread: workingn", 26) = 26
18212 write(1, "Secondary thread: donen", 23) = 23
18212 exit(0)                           = ?
18212 +++ exited with 0 +++
18211 write(1, "Initial thread: done", 20) = 20
18211 exit_group(0)                     = ?
18211 +++ exited with 0 +++

Nenzira, mibvunzo. Ndeipi system call inoshandiswa kugadzira tambo itsva? Ko uku kufona kweshinda kunosiyana sei nekufona kwemaitirwo?

Master kirasi: process stack panguva yekufona system

Imwe yeachangobuda strace kugona - kuratidza stack yebasa rekufona panguva yekufona system. Simple muenzaniso:

void do_write(void)
{
    char str[] = "write me to stdoutn";
    if (sizeof(str) != write(STDOUT_FILENO, str, sizeof(str))){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    do_write();
    return EXIT_SUCCESS;
}

Sezvingatarisirwa, chirongwa chinobuda chinova chakanyanya voluminous, uye, kuwedzera kune mureza -k (kufonera stack kuratidza), zvine musoro kusefa system mafoni nemazita:

$ gcc examples/write-simple.c -o write-simple
$ strace -k -e trace=write -o write-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
write(1, "write me to stdoutn", 20)  = 20
 > /lib/x86_64-linux-gnu/libc-2.27.so(__write+0x14) [0x110154]
 > /home/vkazanov/projects-my/strace-post/write-simple(do_write+0x50) [0x78a]
 > /home/vkazanov/projects-my/strace-post/write-simple(main+0x14) [0x7d1]
 > /lib/x86_64-linux-gnu/libc-2.27.so(__libc_start_main+0xe7) [0x21b97]
 > /home/vkazanov/projects-my/strace-post/write-simple(_start+0x2a) [0x65a]
+++ exited with 0 +++

Master class: kukanganisa jekiseni

Uye chimwe chinhu chitsva uye chinobatsira kwazvo: jekiseni rekukanganisa. Here chirongwa, kunyora mitsetse miviri kune inobuda rwizi:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void do_write(const char *str, ssize_t len)
{
    if (len != write(STDOUT_FILENO, str, (size_t)len)){
        perror("write");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{
    (void) argc; (void) argv;

    char str1[] = "write me 1n";
    do_write(str1, sizeof(str1));

    char str2[] = "write me 2n";
    do_write(str2, sizeof(str2));

    return EXIT_SUCCESS;
}

Ngatitsvagei ese ari maviri anonyora mafoni:

$ gcc examples/write-twice.c -o write-twice
$ ./write-twice
write me 1
write me 2
$ strace -e trace=write -owrite-twice.log ./write-twice
write me 1
write me 2
$ cat write-twice.log
write(1, "write me 1n", 12)          = 12
write(1, "write me 2n", 12)          = 12
+++ exited with 0 +++

Zvino tinoshandisa chirevo injectkuisa kukanganisa EBADF mune zvese nyora mafoni:

$ strace -e trace=write -e inject=write:error=EBADF -owrite-twice.log ./write-twice
$ cat write-twice.log
write(1, "write me 1n", 12)          = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = -1 EBADF (Bad file descriptor) (INJECTED)
+++ exited with 1 +++

Zvinonakidza ndezvipi zvikanganiso zvinodzoserwa all the matambudziko write, kusanganisira kufona kwakavanzwa kuseri kwekutyisidzira. Zvine musoro chete kudzosa kukanganisa kwekutanga kwekufona:

$ strace -e trace=write -e inject=write:error=EBADF:when=1 -owrite-twice.log ./write-twice
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12)          = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++

Kana wechipiri:

$ strace -e trace=write -e inject=write:error=EBADF:when=2 -owrite-twice.log ./write-twice
write me 1
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12)          = 12
write(1, "write me 2n", 12)          = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++

Hazvifanirwe kutsanangura mhando yekukanganisa:

$ strace -e trace=write -e fault=write:when=1 -owrite-twice.log ./write-twice
$ cat write-twice.log
write(1, "write me 1n", 12)          = -1 ENOSYS (Function not implemented) (INJECTED)
write(3, "write: Function not implementedn", 32) = 32
+++ exited with 1 +++

Mukubatana nemamwe mireza, unogona "kutyora" kuwana kune yakatarwa faira. Muenzaniso:

$ strace -y -P/tmp/test_file.log -e inject=file:error=ENOENT -o write-file.log ./write-file /tmp/test_file.log
open: No such file or directory
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = -1 ENOENT (No such file or directory) (INJECTED)
+++ exited with 1 +++

Kunze kwekukanganisa jekiseni, anogona suma kunonoka paunenge uchifona kana kugamuchira masaini.

Afterword

Zvinobatsira strace - chishandiso chiri nyore uye chakavimbika. Asi kunze kwekufona kwehurongwa, zvimwe zvikamu zvekushanda kwezvirongwa uye sisitimu yekushandisa inogona kuderedzwa. Semuenzaniso, inogona kuteedzera mafoni kumaraibhurari ane simba. ltrace, vanogona kutarisa mukushanda kweiyo operating system SystemTap ΠΈ ftrace, uye inobvumidza iwe kuti uongorore zvakadzama maitiro echirongwa zvakakwana. Kunyange zvakadaro, zvakadaro strace - mutsara wekutanga wekudzivirira kana paine matambudziko neangu uye evamwe vanhu zvirongwa, uye ini ndinoishandisa kanenge kanoverengeka pasvondo.

Muchidimbu, kana iwe uchida Unix, verenga man 1 strace uye inzwa wakasununguka kutarisa zvirongwa zvako!

Source: www.habr.com

Voeg