Folosirea neobișnuită a limbajului cu

În interiorul kernel-ului Linux, există multe convenții care necesită multă lectură și învățare pentru a înțelege folosirea și scopul lor. Această secțiune evidențiază unele dintre ambiguitățile sau inexactitățile utilizării lui C, concentrându-se pe convențiile C acceptate în kernelul Linux 2.6.







Utilizarea neobișnuită a limbajului C

asmlinkage instruiește compilatorul să treacă parametrii în stiva locală. Aceasta este asociată cu macrocomanda FASTCALL, care îi spune compilatorului (dependent de hardware) să treacă parametrii în registrele cu scop general. Iată o macrocomandă de la include / asm / link, cu:

4 #define asmlinkage CPP_ASMLINKAGE _ atribut_ ((regparm (O)))

5 #define FASTCALL (x) x_ atribut ((regparm (3)))

6 #define fastcall _ atribut_ ((regparm (3)))

Următorul este un exemplu de asmlinkage.

asmlinkage lung sys_gettimeofday (struct timeval _________ utilizator * tv, struct

fus orar ___ utilizator * tz)

UL este adesea introdusă la sfârșitul constantelor numerice pentru a însemna "nesemnate lungi". UL (sau L pentru mult timp) care urmează să fie inserat la compilator pentru a citi tipul de valoare cu mult timp 1. În unele arhitecturi, astfel este posibil să apăsați-hut de preaplin și merge dincolo de tipul de delimitare. De exemplu, un număr întreg de 16 biți poate reprezenta numere de la -32768 la +32767; Un număr întreg nesemnat poate reprezenta numere de la 0 la 65535. Când utilizați UL, scrieți un cod independent pentru arhitectură pentru numere lungi sau măști lungi.

Iată câteva exemple care arată acest lucru din kernel:

18 idefine GOLDEN_RATIO_PRIME 0x9e37000lUL

23 #define ULONG_MAX (-OUL)

39 #define SLAB_POISON 0x00000800UL / * Obiecte otrăvitoare * /

1 Evident, ne referim la nesemnate. Notă. științifice. Ed.

Capitolul 2 • Instrumente de cercetare

Este necesar un cuvânt cheie inline pentru a optimiza execuția funcțiilor, integrând codul acestor funcții în codul de apel. Kernel-ul Linux folosește multe funcții inline declarate statice; Funcția helper "statică" determină compilatorul să încerce să injecteze codul funcției în toate secțiunile de cod care îl apelează și, dacă este posibil, să evite asamblarea codului pentru această funcție. Uneori, compilatorul nu se poate face fără cod de asamblare (în cazul recursivitatii), dar în cele mai multe cazuri, funcțiile Ob-fenomene ca inline statice, pe deplin puse în aplicare în codul de apel.

Scopul unei astfel de implementări este de a elimina toate operațiile inutile efectuate atunci când este apelată funcția. Expresia #define vă permite, de asemenea, să eliminați operațiile asociate funcției de apel și este de obicei folosită pentru a asigura transferabilitatea altor compilatoare și a sistemelor încorporate.

De ce să nu faceți toate funcțiile încorporate? Dezavantajul folosirii încorporării este creșterea codului binar și, uneori, încetinirea accesului la memoria cache a procesorului.

Aceste două cuvinte cheie sunt ignorate de mulți programatori novici. Cuvantul cheie const nu ar trebui sa fie inteles ca o constanta, ci mai degraba ca doar pentru citire. De exemplu, const int este un pointer la un const-integer. Astfel pointerul poate fi schimbat, iar întregul - nu este prezent. Pe de altă parte, int const * jc denotă un const-pointer la un număr întreg atunci când numărul poate fi schimbat și pointerul nu este. Iată un exemplu de utilizare a const:







62 8 static inline prefetch void (const void * x)

630 __ asm____ volatile_ ("datorie 0,% 0". "R" (x));

Cuvântul volatil (temporar) înseamnă o variabilă care nu poate fi modificată fără comentarii; volatile spune compilatorului că are nevoie să reîncarce variabila etichetă de fiecare dată când întâlnește, mai degrabă decât să stocheze și să acceseze copia sa. Un exemplu bun al unei variabile care trebuie marcat ca temporar este variabilele legate de întreruperi, registrele hardware sau variabilele partajate de procesele concurente. Iată un exemplu de utilizare volatilă:

include / linux / spinlock.h 51 typedef struct

O scurtă trecere în revistă a instrumentelor de cercetare a nucleului

volatilă unsigned int lock; 58> spinlock_t;

Având în vedere că const ar trebui să fie tratat doar ca citire, vedem că unele variabile pot fi concurente și volatile (de exemplu, o variabilă care stochează conținutul unui registru hardware actualizat cu acces numai pentru citire).

Această examinare rapidă va permite începătorului hacker-ului de kernel Linux să se simtă mai încrezător atunci când învață codul sursă al kernel-ului.

O scurtă trecere în revistă a instrumentelor de cercetare a nucleului

Magie: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00

Datele: complementul 2, micul endian

Versiune: 1 (actual)

OS / ABI: UNIX - Sistemul V

Tip: EXEC (fișier executabil)

Mașină: Intel 80386

Adresa punctului de intrare: 0x8048310

Startul antetelor programului: 52 (octeți în fișier)

Începerea anteturilor secțiunilor: 10596 (octeți în fișier)

Dimensiunea acestui antet: 52 (bytes)

Capitolul 2 • Instrumente de cercetare

Dimensiunea anteturilor programului: 32 (bytes)

Numărul de anteturi de programe: 6

Dimensiunea anteturilor secțiunii: 40 (octeți)

Numărul de anteturi de secțiuni: 29

Indicele tabelului de șir al secțiunii antetului: 2 6

Dar dumpul antetului programului, obținut cu ajutorul lui readelf cu flagul -1:

Tipul de fișier Elf este EXEC (fișier executabil)

Punctul de intrare 0x8048310

Există 6 anteturi de program, începând cu offset 52

Anteturi program: Tip Offset VirtAddr PhysAddr FileSiz MemSiz Fig Aliniat PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4

INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1 [Interpret de program solicitant: /lib/ld-linux.so.2]

LOAD 0x000000 0x08048000 0x08048000 0x00498 0x00498 R E 0x1000

LOAD 0x000498 0x08049498 0x08049498 0x00108 0x00120 RW 0x1000

DYNAMIC 0x0004ac 0x080494ac 0x080494ac 0x000c8 0x000c8 RW 0x4

NOTĂ 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4 Secțiunea pentru

2 .interp. Notă.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r rel.dyn .rel.plt .init .pit .text .fini .rodata

3 .data .eh_frame .dynamic .ctors .dtors .got .bss

Comanda hexdump afișează conținutul fișierului specificat în format hexazecimal, ASCII sau octal. [Notă: versiunile mai vechi de Linux au folosit de asemenea și od (octal dump). Acum cele mai multe sisteme folosesc hexdump.]

De exemplu, pentru a vizualiza primele 64 de biți din fișierul ELF a.out în modul hexazecimal, trebuie să tastați următoarele:

Lwp> hexdump -x -n 64 a.out

F 151c 01010001 0000 0000 0000 0000

0000010 0002 0003 0001 0000 8310 0804 0034 0000

0000020 2964 0000 0000 0000 0034 0020 0006 0028

Ola 001a 0006 0000 0034 0000 8034 0804

Spune kernelul: ascultarea mesajelor kernel-ului

Instrumentul de executare afișează toate caracterele din fișierul obiect. Afișează valorile caracterelor, tipul și numele acestora. Acest utilitar nu este la fel de util ca restul, dar totuși poate fi util atunci când se depanează fișiere de bibliotecă.

Comanda ar, sau arhiva (arhiva), ajută la susținerea bibliotecilor indexate utilizate de linker. Comanda ag colectează unul sau mai multe fișiere obiect într-o singură bibliotecă. În plus, poate aloca un fișier de obiecte separat din bibliotecă. Cel mai adesea, puteți vedea comanda ag din fișierul Makefile. Este uneori folosit pentru combinarea funcțiilor utilizate într-o singură bibliotecă. De exemplu, să presupunem că aveți o funcție care analizează fișierul batch și cauzează unele date sau apeluri pentru a prelua informații pentru registrele hardware specificate. Această funcție este necesară pentru mai multe programe executabile. Arhivarea acestei funcții într-o bibliotecă separată vă va ușura controlul versiunilor prin plasarea funcției într-un singur loc.







Trimiteți-le prietenilor: