Linuxi süsteemikõnede õpetus koos C -ga

Linux System Call Tutorial With C



Meie viimases artiklis Linuxi süsteemikõned , Määratlesin süsteemikõne, arutasin põhjuseid, miks neid programmis kasutada võiks, ning uurisin nende eeliseid ja puudusi. Ma tõin isegi lühikese näite kokkupanekul C -s. See illustreeris asjaolu ja kirjeldas, kuidas helistada, kuid ei teinud midagi produktiivset. Mitte just põnev arendusharjutus, kuid illustreeris asja olemust.

Selles artiklis kasutame oma C -programmi tegeliku töö tegemiseks tegelikke süsteemikõnesid. Esiteks vaatame üle, kas peate kasutama süsteemikõnet, seejärel esitame näite sendfile () kõne abil, mis võib oluliselt kopeerida failide kopeerimist. Lõpuks vaatame üle mõned punktid, mida Linuxi süsteemikõnede kasutamisel meeles pidada.







Ehkki see on vältimatu, kasutate oma C -arenduskarjääri mingil hetkel süsteemikõnet, kui te ei sihi suure jõudluse või teatud tüüpi funktsionaalsust, hoolitsevad enamiku Linuxi distributsioonide hulka kuuluvad glibci raamatukogu ja muud põhiteegid teie vajadustele.



Glibci standardraamatukogu pakub platvormideülest ja hästi testitud raamistikku funktsioonide täitmiseks, mis muidu nõuaksid süsteemipõhiseid süsteemikõnesid. Näiteks saate lugeda faile failidega fscanf (), fread (), getc () jne või kasutada Linuxi süsteemikõnet read (). Glibc -funktsioonid pakuvad rohkem funktsioone (st parem vigade käsitlemine, vormindatud IO jne) ja töötavad mis tahes süsteemi glibc -toega.



Teisest küljest on aegu, kus kompromissitu jõudlus ja täpne teostus on kriitilised. Pakend, mida pakub fread (), lisab üldkulusid ja on küll väike, kuid pole täiesti läbipaistev. Lisaks ei pruugi te soovida või vajada ümbrise pakutavaid lisafunktsioone. Sellisel juhul teenib teid kõige paremini süsteemikõne.





Süsteemikõnesid saate kasutada ka funktsioonide täitmiseks, mida glibc veel ei toeta. Kui teie glibci koopia on ajakohane, pole see tõenäoliselt probleem, kuid uuemate tuumadega vanemate distributsioonide arendamine võib seda tehnikat nõuda.

Nüüd, kui olete lugenud lahtiütlemisi, hoiatusi ja võimalikke ümbersõite, uurime nüüd mõnda praktilist näidet.



Mis protsessor meil on?

Küsimus, mida enamik programme ilmselt ei arva küsida, kuid siiski õige. See on näide süsteemikutsest, mida ei saa glibc -ga dubleerida ja mis pole kaetud glibc -ümbrisega. Selles koodis kutsume funktsiooni getcpu () otse funktsiooni syscall () kaudu. Syscall -funktsioon töötab järgmiselt.

süsteemikõne(SYS_call,arg1,arg2,...);

Esimene argument SYS_call on määratlus, mis tähistab süsteemikõne numbrit. Kui lisate sys/syscall.h, on need ka kaasatud. Esimene osa on SYS_ ja teine ​​osa on süsteemikõne nimi.

Kõne argumendid lähevad eespool arg1, arg2. Mõned kõned nõuavad rohkem argumente ja need jätkuvad man -lehel järjekorras. Pidage meeles, et enamiku argumentide, eriti tagastuste puhul, on vaja kursoreid massiivide või mälu salvestamiseks malloc -funktsiooni kaudu.

näide1.c

#kaasake
#kaasake
#kaasake
#kaasake

intpeamine() {

allkirjastamataProtsessor,sõlm;

// Hankige süsteemikõne kaudu praegune CPU tuum ja NUMA sõlm
// Pange tähele, et sellel pole glibc ümbrist, nii et me peame selle otse nimetama
süsteemikõne(SYS_getcpu, &Protsessor, &sõlm,NULL);

// Kuva teave
printf ('See programm töötab protsessori tuumas %u ja NUMA sõlmes %u. n n',Protsessor,sõlm);

tagasi 0;

}

Kompileerimiseks ja käivitamiseks:

gcc näide1.c -o näide 1
./näide1

Huvitavate tulemuste saamiseks võite keerutada lõime pthreads raamatukogu kaudu ja seejärel helistada sellele funktsioonile, et näha, millisel protsessoril teie niit töötab.

Saatmisfail: suurepärane jõudlus

Sendfile on suurepärane näide jõudluse suurendamisest süsteemikõnede kaudu. Funktsioon sendfile () kopeerib andmed ühest failikirjutajast teise. Selle asemel, et kasutada mitut fread () ja fwrite () funktsiooni, teostab sendfail ülekande kerneli ruumis, vähendades üldkulusid ja suurendades seeläbi jõudlust.

Selles näites kopeerime 64 MB andmeid ühest failist teise. Ühes testis kasutame standardraamatukogus standardseid lugemis-/kirjutamismeetodeid. Teises osas kasutame nende andmete edastamiseks ühest kohast teise süsteemikõnesid ja Sendfile () kõnet.

test1.c (glibc)

#kaasake
#kaasake
#kaasake
#kaasake

#define BUFFER_SIZE 67108864
#define BUFFER_1 'puhver1'
#define BUFFER_2 'puhver2'

intpeamine() {

FILE*vale, *lõpp;

printf (' nI/O test traditsiooniliste glibc -funktsioonidega. n n');

// Haara BUFFER_SIZE puhver.
// Puhvris on juhuslikke andmeid, kuid me ei hooli sellest.
printf ('64 MB puhvri eraldamine:');
süsi *puhver= (süsi *) malloc (BUFFER_SIZE);
printf ('VALMIS n');

// Kirjutage puhver fOut
printf ('Andmete kirjutamine esimesse puhvrisse:');
vale= avada (PUHVER_1, 'wb');
fwrite (puhver, suurus(süsi),BUFFER_SIZE,vale);
fclose (vale);
printf ('VALMIS n');

printf ('Andmete kopeerimine esimesest failist teise:');
lõpp= avada (PUHVER_1, 'rb');
vale= avada (PUHVER_2, 'wb');
fread (puhver, suurus(süsi),BUFFER_SIZE,lõpp);
fwrite (puhver, suurus(süsi),BUFFER_SIZE,vale);
fclose (lõpp);
fclose (vale);
printf ('VALMIS n');

printf ('Puhvri vabastamine:');
tasuta (puhver);
printf ('VALMIS n');

printf ('Failide kustutamine:');
eemaldada (PUHVER_1);
eemaldada (PUHVER_2);
printf ('VALMIS n');

tagasi 0;

}

test2.c (süsteemikõned)

#kaasake
#kaasake
#kaasake
#kaasake
#kaasake
#kaasake
#kaasake
#kaasake
#kaasake

#define BUFFER_SIZE 67108864

intpeamine() {

intvale,lõpp;

printf (' nI/O test sendfailiga () ja sellega seotud süsteemikõned. n n');

// Haara BUFFER_SIZE puhver.
// Puhvris on juhuslikke andmeid, kuid me ei hooli sellest.
printf ('64 MB puhvri eraldamine:');
süsi *puhver= (süsi *) malloc (BUFFER_SIZE);
printf ('VALMIS n');


// Kirjutage puhver fOut
printf ('Andmete kirjutamine esimesse puhvrisse:');
vale=lahti('puhver1',O_RDONLY);
kirjutada(vale, &puhver,BUFFER_SIZE);
Sulge(vale);
printf ('VALMIS n');

printf ('Andmete kopeerimine esimesest failist teise:');
lõpp=lahti('puhver1',O_RDONLY);
vale=lahti('puhver2',O_RDONLY);
saada fail(vale,lõpp, 0,BUFFER_SIZE);
Sulge(lõpp);
Sulge(vale);
printf ('VALMIS n');

printf ('Puhvri vabastamine:');
tasuta (puhver);
printf ('VALMIS n');

printf ('Failide kustutamine:');
linkimise tühistamine('puhver1');
linkimise tühistamine('puhver2');
printf ('VALMIS n');

tagasi 0;

}

Testide koostamine ja läbiviimine 1 ja 2

Nende näidete koostamiseks vajate oma distributsioonile installitud arendustööriistu. Debianis ja Ubuntus saate selle installida järgmiselt:

asjakohanepaigaldadaehitamiseks vajalik

Seejärel kompileerige:

gcctest1.c-võitest1&& gcctest2.c-võitest2

Mõlema käitamiseks ja jõudluse testimiseks käivitage:

aega./test1&& aega./test2

Peaksite saama sellised tulemused:

I/O test traditsiooniliste glibc -funktsioonidega.

64 MB puhvri eraldamine: VALMIS
Andmete kirjutamine esimesse puhvrisse: VALMIS
Andmete kopeerimine esimesest failist teise: VALMIS
Puhvri vabastamine: VALMIS
Failide kustutamine: VALMIS
reaalne 0m0.397s
kasutaja 0m0.000s
sys 0m0,203s
I/O test sendfailiga () ja sellega seotud süsteemikõned.
64 MB puhvri eraldamine: VALMIS
Andmete kirjutamine esimesse puhvrisse: VALMIS
Andmete kopeerimine esimesest failist teise: VALMIS
Puhvri vabastamine: VALMIS
Failide kustutamine: VALMIS
päris 0m0.019s
kasutaja 0m0.000s
sys 0m0.016s

Nagu näete, töötab süsteemikõnesid kasutav kood palju kiiremini kui glibci ekvivalent.

Asjad, mida meeles pidada

Süsteemikõned võivad suurendada jõudlust ja pakkuda lisafunktsionaalsust, kuid need ei ole ilma puudusteta. Peate kaaluma süsteemikõnede eeliseid platvormi teisaldatavuse puudumise ja mõnikord vähenenud funktsionaalsuse suhtes võrreldes raamatukogu funktsioonidega.

Mõne süsteemikõne kasutamisel peate hoolitsema selle eest, et kasutaksite süsteemikõnedest tagastatud ressursse, mitte raamatukogu funktsioone. Näiteks FILE struktuur, mida kasutatakse funktsioonide glibc fopen (), fread (), fwrite () ja fclose () jaoks, ei ole sama mis failikirjelduse number avatud () süsteemikutsest (tagastatakse täisarvuna). Nende segamine võib põhjustada probleeme.

Üldiselt on Linuxi süsteemikõnedel vähem kaitseradu kui glibc -funktsioonidel. Kuigi on tõsi, et süsteemikõnedel on mõningaid tõrkeid ja aruandlust, saate glibc -funktsioonist üksikasjalikuma funktsionaalsuse.

Ja lõpetuseks mõni sõna turvalisusest. Süsteemikõned ühenduvad otse kerneliga. Linuxi kernelil on küll ulatuslik kaitse kasutajate maad tekitavate võltsingute eest, kuid avastamata vead on olemas. Ärge usaldage, et süsteemikõne kinnitab teie sisendi või isoleerib teid turvaprobleemidest. Mõistlik on tagada süsteemikõnele edastatud andmete desinfitseerimine. Loomulikult on see hea nõuanne iga API kõne puhul, kuid te ei saa kerneliga töötamisel olla ettevaatlik.

Loodan, et teile meeldis see sügavam sukeldumine Linuxi süsteemikõnede maale. Linuxi süsteemikõnede täieliku loendi leiate meie põhiloendist.