Strace mu Linux: mbiri, kapangidwe ndi kugwiritsa ntchito

Strace mu Linux: mbiri, kapangidwe ndi kugwiritsa ntchito

M'machitidwe ogwiritsira ntchito a Unix, kulumikizana kwa pulogalamu ndi dziko lakunja ndi makina ogwiritsira ntchito kumachitika kudzera mumagulu ang'onoang'ono - mafoni a dongosolo. Izi zikutanthauza kuti pazolinga zowongolera zitha kukhala zothandiza kuti akazonde mafoni omwe akuchitidwa ndi njira.

Ntchito imakuthandizani kuwunika "moyo wapamtima" wa mapulogalamu pa Linux strace, yomwe ndi nkhani ya m’nkhaniyi. Zitsanzo za kugwiritsa ntchito zida za akazitape zimatsagana ndi mbiri yachidule strace ndi kufotokoza za mapangidwe a mapulogalamu otere.

Zamkatimu

Chiyambi cha mitundu

Mawonekedwe akulu pakati pa mapulogalamu ndi OS kernel ku Unix ndi mafoni amtundu. mafoni adongosolo, zikwangwani), kuyanjana kwa mapulogalamu ndi akunja kumachitika kudzera mwa iwo okha.

Koma mu mtundu woyamba wa Unix (Mtundu wa 6 Unix, 1975) panalibe njira zabwino zowonera machitidwe a ogwiritsa ntchito. Kuti athetse vutoli, Bell Labs isintha mpaka mtundu wina (Mtundu wa 7 Unix, 1979) adakonza kuyitanira kwadongosolo latsopano - ptrace.

ptrace idapangidwa makamaka kuti ikhale yosokoneza, koma pofika kumapeto kwa zaka za m'ma 80s (m'nthawi yamalonda). Kutulutsidwa kwa System V 4) pazifukwa zimenezi, zida zongogwiritsa ntchito movutikira kwambiriβ€”zozimitsa makinaβ€”zinaonekera ndipo zinayamba kugwiritsidwa ntchito kwambiri.

Yoyamba mtundu womwewo wa strace unasindikizidwa ndi Paul Cronenburg pamndandanda wamakalata wa comp.sources.sun mu 1992 ngati njira ina yolumikizira yotsekedwa. trace kuchokera ku Sun. Zonse ziwiri ndi zoyambirira zidapangidwira SunOS, koma pofika 1994 strace idatumizidwa ku System V, Solaris ndi Linux yomwe ikukula kwambiri.

Masiku ano strace imangothandiza Linux ndipo imadalira zomwezo ptrace, yodzaza ndi zowonjezera zambiri.

Wosamalira wamakono (komanso wogwira ntchito kwambiri). strace - Dmitry Levin. Chifukwa cha iye, ntchitoyo idapeza zinthu zapamwamba monga jekeseni wolakwika pama foni amachitidwe, kuthandizira pazomangamanga zosiyanasiyana ndipo, chofunikira kwambiri, mascot. Magwero osavomerezeka amanena kuti chisankhocho chinagwera pa nthiwatiwa chifukwa cha mgwirizano pakati pa mawu achirasha akuti "nthiwatiwa" ndi mawu achingerezi "strace".

Ndikofunikiranso kuti kuyimbira foni ndi zotsatsira za ptrace sikunaphatikizidwepo mu POSIX, ngakhale mbiri yakale ndikukhazikitsa mu Linux, FreeBSD, OpenBSD ndi Unix yachikhalidwe.

Strace chipangizo mwachidule: Piglet Trace

"Simukuyenera kumvetsetsa izi" (Dennis Ritchie, ndemanga mu Version 6 Unix source code)

Kuyambira ndili mwana, sindingathe kuyimilira mabokosi akuda: Sindinasewere ndi zidole, koma ndinayesera kumvetsetsa kapangidwe kawo (akuluakulu amagwiritsa ntchito mawu akuti "kusweka," koma musakhulupirire malirime oipa). Mwina ichi ndichifukwa chake chikhalidwe chosavomerezeka cha Unix yoyamba ndi kayendetsedwe kamakono kotsegula kamene kali pafupi ndi ine.

Pazolinga za nkhaniyi, sizomveka kusokoneza code code ya strace, yomwe yakula kwa zaka zambiri. Koma pasakhale zinsinsi zotsalira kwa owerenga. Chifukwa chake, kuti ndiwonetse mfundo yoyendetsera mapulogalamu otere, ndipereka kachidindo kakang'ono ka tracer - Piglet Trace (ptr). Simadziwa kuchita chilichonse chapadera, koma chinthu chachikulu ndi kuyitana kwa pulogalamu - imatuluka:

$ 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 imazindikira pafupifupi mazana a mafoni a Linux (onani. tebulo) ndipo imagwira ntchito pazomanga za x86-64 zokha. Izi ndizokwanira pazolinga zamaphunziro.

Tiyeni tiwone ntchito ya wojambula wathu. Pankhani ya Linux, ochotsa zolakwika ndi otsata amagwiritsa ntchito, monga tafotokozera pamwambapa, foni ya ptrace system. Zimagwira ntchito podutsa mkangano woyamba zizindikiritso za malamulo, zomwe timangofunikira PTRACE_TRACEME, PTRACE_SYSCALL ΠΈ PTRACE_GETREGS.

Tracer imayamba mwachizolowezi cha Unix: fork(2) imayambitsa ndondomeko ya mwana, yomwe imagwiritsanso ntchito exec(3) imayambitsa pulogalamu yomwe ikuphunziridwa. Chinyengo chokha apa ndizovuta ptrace(PTRACE_TRACEME) kale exec: Ndondomeko ya mwana ikuyembekeza ndondomeko ya makolo kuti iziziyang'anira:

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");
}

Njira ya makolo iyenera kuyimba foni wait(2) mu ndondomeko ya mwana, ndiye kuti, onetsetsani kuti kusintha kwa trace mode kwachitika:

/* 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");

Pakadali pano, zokonzekera zatha ndipo mutha kupitilira molunjika pakutsata mafoni amtundu wanthawi zonse.

Chovuta ptrace(PTRACE_SYSCALL) zimatsimikizira kuti pambuyo pake wait kholo lidzamaliza kuyimba foni isanayimbidwe kapena ikangomaliza. Pakati pa mafoni awiri mutha kuchita chilichonse: sinthani foniyo ndi ina, sinthani zotsutsana kapena mtengo wobwezera.

Timangofunika kuitana lamulo kawiri ptrace(PTRACE_GETREGS)kuti apeze boma la registry rax isanayambe kuyimba (nambala yoyimba dongosolo) ndipo nthawi yomweyo (mtengo wobwezera).

Kwenikweni, kuzungulira:

/* 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);
}

Ndiye tracer yonse. Tsopano mukudziwa komwe mungayambire kunyamula kotsatira Malangizo pa Linux.

Zofunika: Kuyambitsa pulogalamu yoyendetsa strace

Monga gawo loyamba logwiritsa ntchito strace, mwina ndiyenera kutchula njira yosavuta - kuyambitsa pulogalamu yomwe ikuyenda strace.

Kuti tisayang'ane pamndandanda wopanda malire wamapulogalamu wamba, timalemba pulogalamu yochepa Π²ΠΎΠΊΡ€ΡƒΠ³ 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;
}

Tiyeni tipange pulogalamuyo ndikuwonetsetsa kuti ikugwira ntchito:

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

Ndipo potsiriza, tiyeni tiyendetse pansi pa 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)                           = ?

"Mawu" kwambiri komanso osaphunzira kwambiri. Pali mavuto awiri apa: kutulutsa kwa pulogalamu kumasakanizidwa ndi zotuluka strace ndi mafoni ochuluka omwe satisangalatsa.

Mutha kulekanitsa mayendedwe amtundu wa pulogalamuyo ndikutulutsa zolakwika pogwiritsa ntchito -o switch, yomwe imawongoleranso mndandanda wamayimbidwe amachitidwe ku fayilo yotsutsana.

Imakhalabe kuthana ndi vuto la mafoni "owonjezera". Tiyerekeze kuti timangokonda mafoni write. Chinsinsi -e amakulolani kuti mutchule mawu omwe mafoni amasefedwe. Njira yodziwika bwino kwambiri ndiyo, mwachilengedwe, trace=*, zomwe mungathe kusiya mafoni okha omwe amatisangalatsa.

Mukagwiritsidwa ntchito nthawi imodzi -o ΠΈ -e tidzapeza:

$ 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 +++

Kotero, mukuwona, ndizosavuta kuwerenga.

Mutha kuchotsanso mafoni amachitidwe - mwachitsanzo, omwe amagwirizana ndi kugawa ndikumasula kukumbukira:

$ 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 +++

Zindikirani kufuula komwe kwathawa pamndandanda wamayimbidwe osaphatikizidwa: izi zimafunika ndi chipolopolo cholamula. chipolopolo).

Mu mtundu wanga wa glibc, kuyimba foni kumathetsa ntchitoyi exit_group, osati mwambo _exit. Izi ndizovuta kugwira ntchito ndi mafoni amtundu: mawonekedwe omwe wopanga mapulogalamuwa amagwirira ntchito sizigwirizana mwachindunji ndi mafoni amtundu. Komanso, zimasintha pafupipafupi kutengera kukhazikitsa ndi nsanja.

Zofunika: kujowina ndondomeko pa ntchentche

Poyamba, pulogalamu ya ptrace imayitanira pomwe idamangidwa strace, zitha kugwiritsidwa ntchito poyendetsa pulogalamuyo mwanjira yapadera. Izi mwina zidamveka zomveka m'masiku a Version 6 Unix. Masiku ano, izi sizokwanira: nthawi zina muyenera kufufuza zovuta za pulogalamu yogwira ntchito. Chitsanzo chodziwika bwino ndi njira yotsekedwa pa chogwirira kapena kugona. Choncho zamakono strace akhoza kujowina ndondomeko pa ntchentche.

Chitsanzo chozizira mapulogalamu:

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;
}

Tiyeni tipange pulogalamuyo ndikuwonetsetsa kuti yazizira:

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

Tsopano tiyeni tiyese kujowina:

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

Pulogalamu yoletsedwa ndi kuyimba pause. Tiyeni tiwone momwe amachitira ndi zizindikiro:

$ 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 +++

Tinayambitsa pulogalamu yachisanu ndikulowa nawo pogwiritsa ntchito strace. Zinthu ziwiri zidadziwika bwino: kuyimba kwapaintaneti kumanyalanyaza ma siginecha opanda othandizira ndipo, chosangalatsa kwambiri, owunikira amangoyimba mafoni, komanso ma sign omwe akubwera.

Chitsanzo: Kutsata Njira za Ana

Kugwira ntchito ndi njira kudzera pa foni fork - maziko a Unixes onse. Tiyeni tiwone momwe strace imagwirira ntchito ndi mtengo wopangira njira pogwiritsa ntchito chitsanzo cha "kuswana" kosavuta. mapulogalamu:

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);
}

Apa njira yoyambirira imapanga njira ya mwana, zonse zimalemba mpaka kutulutsa kokhazikika:

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

Mwachikhazikitso, tidzangowona mafoni amtundu kuchokera pamachitidwe a makolo:

$ 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 +++

Mbendera imakuthandizani kuti muzitha kuyang'anira mtengo wonse wanjira -f, amene strace amayang'anira dongosolo kuitana mu ndondomeko mwana. Izi zimawonjezera pamzere uliwonse wazotulutsa pid ndondomeko yomwe imapanga ndondomeko:

$ 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 +++

Munkhaniyi, kusefa ndi gulu la mafoni amtundu kumatha kukhala kothandiza:

$ 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 +++

Mwa njira, ndi foni yanji yomwe imagwiritsidwa ntchito popanga njira yatsopano?

Chitsanzo: njira zamafayilo m’malo mwa zogwirira

Kudziwa zofotokozera mafayilo ndikothandiza, koma mayina a mafayilo omwe pulogalamu imawapeza amathanso kukhala othandiza.

Chotsatira pulogalamuyi amalemba mzere ku fayilo yakanthawi:

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;
}

Panthawi yoyimba bwino strace iwonetsa mtengo wa nambala yofotokozera yomwe idaperekedwa ku foni yadongosolo:

$ 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 +++

Ndi mbendera -y Chidachi chikuwonetsa njira yopita ku fayilo yomwe wofotokozera amafanana:

$ 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 +++

Chitsanzo: Kutsata Mafayilo

Chinthu chinanso chothandiza: wonetsani mafoni amtundu okha omwe amalumikizidwa ndi fayilo inayake. Ena pulogalamuyi imawonjezera mzere ku fayilo yosasinthika yomwe idaperekedwa ngati mkangano:

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;
}

zotsatira strace amawonetsa zambiri zosafunikira. Mbendera -P ndi mkangano zimayambitsa strace kusindikiza mafoni okha ku fayilo yotchulidwa:

$ 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 +++

Chitsanzo: Mapologalamu Ambiri

Zothandiza strace ingathandizenso pogwira ntchito ndi ma multi-threads pulogalamu. Pulogalamu yotsatirayi imalemba zotuluka mumitsinje iwiri:

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);
}

Mwachilengedwe, iyenera kuphatikizidwa ndi moni wapadera kwa wolumikizira - -pthread mbendera:

$ 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
$

Sakanizani -f, monga momwe zimakhalira nthawi zonse, zidzawonjezera pid ya ndondomekoyi kumayambiriro kwa mzere uliwonse.

Mwachilengedwe, sitikulankhula za chizindikiritso cha ulusi m'lingaliro la kukhazikitsidwa kwa muyezo wa POSIX Threads, koma za chiwerengero chomwe chimagwiritsidwa ntchito ndi wopanga ntchito ku Linux. Kuchokera kumalingaliro omalizira, palibe njira kapena ulusi - pali ntchito zomwe ziyenera kugawidwa pakati pa makina omwe alipo.

Mukamagwira ntchito ndi ulusi wambiri, kuyimba foni kumachulukanso:

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

Ndizomveka kudziletsa nokha kuwongolera kasamalidwe ndi mafoni adongosolo okha 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 +++

Mwa njira, mafunso. Ndi foni yanji yomwe imagwiritsidwa ntchito popanga ulusi watsopano? Kodi kuyitana kwa ulusi uku kumasiyana bwanji ndi kuyitanira kwa njira?

Kalasi ya Master: process stack panthawi yoyimba foni

Mmodzi wa posachedwapa anaonekera strace kuthekera - kuwonetsa kuchuluka kwa mafoni ogwira ntchito panthawi yoyimba foni. Zosavuta chitsanzo:

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;
}

Mwachibadwa, pulogalamu linanena bungwe limakhala voluminous kwambiri, ndipo, kuwonjezera mbendera -k (chiwonetsero cha stack), ndizomveka kusefa mafoni amtundu ndi dzina:

$ 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: jekeseni wolakwika

Ndipo chinthu china chatsopano komanso chothandiza kwambiri: jekeseni wolakwika. Pano pulogalamuyi, kulemba mizere iwiri kumtsinje wotuluka:

#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;
}

Tiyeni titsate ma call onse awiri:

$ 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 +++

Tsopano tigwiritsa ntchito mawuwo injectkuyika cholakwika EBADF mumayitanidwe onse:

$ 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 +++

Ndizosangalatsa zomwe zolakwika zabwezedwa onse zovuta write, kuphatikizapo kuyitana kobisika kumbuyo kwa mantha. Ndizomveka kubweza cholakwika pakuyimba koyamba:

$ 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 +++

Kapena yachiwiri:

$ 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 +++

Sikoyenera kufotokoza mtundu wolakwika:

$ 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 +++

Kuphatikiza ndi mbendera zina, mutha "kuswa" kupeza fayilo inayake. Chitsanzo:

$ 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 +++

Kupatula jekeseni zolakwika, mungathe yambitsani kuchedwa poyimba kapena kulandira ma sign.

Pambuyo pake

Zothandiza strace - chida chosavuta komanso chodalirika. Koma kuwonjezera pa kuyimba foni, mbali zina za kagwiritsidwe ntchito ka mapulogalamu ndi makina ogwiritsira ntchito amatha kusinthidwa. Mwachitsanzo, imatha kuyang'anira mafoni kuma library olumikizidwa kwambiri. ltrace, amatha kuyang'ana momwe ntchito yogwirira ntchito imagwirira ntchito SystemTap ΠΈ phokoso, ndikukulolani kuti mufufuze mozama momwe pulogalamuyo ikuyendera wangwiro. Ngakhale zili choncho strace - mzere woyamba wa chitetezo pakakhala mavuto ndi mapulogalamu anga ndi anthu ena, ndipo ndimagwiritsa ntchito kangapo pa sabata.

Mwachidule, ngati mumakonda Unix, werengani man 1 strace ndipo omasuka kuyang'ana pa mapulogalamu anu!

Source: www.habr.com

Kuwonjezera ndemanga