„Linux“ sistemos skambučių pamoka su C.

Linux System Call Tutorial With C



Paskutiniame mūsų straipsnyje apie „Linux“ sistemos skambučiai , Aš apibrėžiau sistemos iškvietimą, aptariau priežastis, kodėl juos galima naudoti programoje, ir įsigilinau į jų privalumus ir trūkumus. Aš netgi pateikiau trumpą pavyzdį surinkimo metu C. Tai iliustravo esmę ir aprašė, kaip skambinti, bet nieko nedavė. Ne visai jaudinantis vystymosi pratimas, tačiau jis iliustravo esmę.

Šiame straipsnyje mes naudosime faktinius sistemos skambučius, kad atliktume tikrą darbą mūsų C programoje. Pirma, peržiūrėsime, ar jums reikia naudoti sistemos skambutį, tada pateiksime pavyzdį naudodami sendfile () skambutį, kuris gali žymiai pagerinti failų kopijavimo našumą. Galiausiai apžvelgsime kai kuriuos dalykus, kuriuos reikia atsiminti naudojant „Linux“ sistemos skambučius.







Nors tai neišvengiama, tam tikru savo C kūrimo karjeros momentu naudosite sistemos iškvietimą, nebent siekiate didelio našumo ar tam tikro tipo funkcijų, „glibc“ biblioteka ir kitos pagrindinės bibliotekos, įtrauktos į pagrindinius „Linux“ platinimus, pasirūpins dauguma jūsų poreikius.



„Glibc“ standartinė biblioteka suteikia kelių platformų, gerai išbandytą sistemą, skirtą funkcijoms vykdyti, kurioms kitu atveju prireiktų konkrečios sistemos iškvietimų. Pvz., Galite skaityti failą naudodami fscanf (), fread (), getc () ir tt arba naudoti skaitymo () „Linux“ sistemos iškvietimą. „Glibc“ funkcijos suteikia daugiau funkcijų (t. Y. Geresnį klaidų valdymą, suformatuotą IO ir pan.) Ir veiks su bet kokia sistemos „glibc“ atrama.



Kita vertus, yra atvejų, kai bekompromisis veikimas ir tikslus vykdymas yra labai svarbūs. Apvyniojimas, kurį teikia fread (), pridės pridėtinių išlaidų ir, nors ir nedidelis, nėra visiškai skaidrus. Be to, galbūt nenorite ar nereikia papildomų įvyniojimo funkcijų. Tokiu atveju jums geriausiai tinka sistemos skambutis.





Taip pat galite naudoti sistemos skambučius, kad atliktumėte funkcijas, kurių dar nepalaiko „glibc“. Jei jūsų „Glibc“ kopija yra naujausia, tai vargu ar bus problema, tačiau kuriant senesnius platinimus su naujesniais branduoliais gali prireikti šios technikos.

Dabar, kai perskaitėte atsisakymą, įspėjimus ir galimus aplinkkelius, dabar panagrinėkime keletą praktinių pavyzdžių.



Kokį CPU mes naudojame?

Klausimas, kurio dauguma programų tikriausiai nemano užduoti, bet vis tiek yra teisingas. Tai yra sistemos iškvietimo pavyzdys, kurio negalima dubliuoti naudojant „glibc“ ir kuris nėra padengtas „glibc“ įvyniojimu. Šiame kode mes iškviesime getcpu () skambutį tiesiogiai per funkciją syscall (). „Syscall“ funkcija veikia taip:

sistemos skambutis(SYS_call,arg1,arg2,...);

Pirmasis argumentas, SYS_call, yra apibrėžimas, nurodantis sistemos iškvietimo numerį. Kai įtraukiate sys/syscall.h, jie yra įtraukti. Pirmoji dalis yra SYS_, o antroji - sistemos skambučio pavadinimas.

Skambučio argumentai yra aukščiau arg1, arg2. Kai kuriems skambučiams reikia daugiau argumentų ir jie bus tęsiami eilės tvarka iš savo žinyno puslapio. Atminkite, kad daugumai argumentų, ypač dėl grąžinimo, reikės rodyklių, skirtų įrašyti masyvus ar atmintį, priskirtą naudojant „malloc“ funkciją.

pavyzdys1.c

#įtraukti
#įtraukti
#įtraukti
#įtraukti

tarptpagrindinis() {

nepasirašytasprocesorius,mazgas;

// Gaukite dabartinį procesoriaus branduolį ir NUMA mazgą per sistemos skambutį
// Atkreipkite dėmesį, kad tai neturi „glibc“ įvyniojimo, todėl turime jį vadinti tiesiogiai
sistemos skambutis(SYS_getcpu, &procesorius, &mazgas,NULL);

// Rodyti informaciją
printf ('Ši programa veikia CPU šerdyje %u ir NUMA mazge %u. n n',procesorius,mazgas);

grįžti 0;

}

Norėdami sudaryti ir paleisti:

gcc pavyzdys1.c -o pavyzdys1
./1 pavyzdys

Norėdami gauti įdomesnių rezultatų, galite sukti gijas per pthreads biblioteką ir tada paskambinti į šią funkciją, kad pamatytumėte, kuriame procesoriuje veikia jūsų siūlas.

Siuntimo failas: puikus našumas

„Sendfile“ yra puikus pavyzdys, kaip pagerinti našumą naudojant sistemos skambučius. Funkcija sendfile () kopijuoja duomenis iš vieno failo aprašo į kitą. Užuot naudojęs kelias „fread“ () ir „fwrite“ () funkcijas, „sendfile“ atlieka perdavimą branduolio erdvėje, sumažindamas pridėtines išlaidas ir taip padidindamas našumą.

Šiame pavyzdyje mes nukopijuosime 64 MB duomenų iš vieno failo į kitą. Vieno testo metu standartinėje bibliotekoje naudosime standartinius skaitymo/rašymo metodus. Kitu atveju mes naudosime sistemos skambučius ir sendfile () skambutį, kad šie duomenys būtų perduodami iš vienos vietos į kitą.

test1.c (glibc)

#įtraukti
#įtraukti
#įtraukti
#įtraukti

#define BUFFER_SIZE 67108864
#define BUFFER_1 'buferis1'
#define BUFFER_2 'buferis2'

tarptpagrindinis() {

FILE*neteisingai, *galas;

printf (' nĮvesties/išvesties testas su tradicinėmis „glibc“ funkcijomis. n n');

// Paimkite BUFFER_SIZE buferį.
// Buferyje bus atsitiktinių duomenų, bet mums tai nerūpi.
printf („Skiriamas 64 MB buferis:“);
anglis *buferis= (anglis *) malloc (BUFFER_SIZE);
printf ('PADARYTA n');

// Įrašykite buferį į fOut
printf („Duomenų įrašymas į pirmąjį buferį:“);
neteisingai= fopen (BUFFER_1, 'wb');
rašyti (buferis, dydis(anglis),BUFFER_SIZE,neteisingai);
fclose (neteisingai);
printf ('PADARYTA n');

printf („Duomenų kopijavimas iš pirmo failo į antrą:“);
galas= fopen (BUFFER_1, „rb“);
neteisingai= fopen (PUSLAPIS_2, 'wb');
fread (buferis, dydis(anglis),BUFFER_SIZE,galas);
rašyti (buferis, dydis(anglis),BUFFER_SIZE,neteisingai);
fclose (galas);
fclose (neteisingai);
printf ('PADARYTA n');

printf ('Išlaisvinamas buferis:');
Laisvas (buferis);
printf ('PADARYTA n');

printf („Failų trynimas“:);
pašalinti (BUFFER_1);
pašalinti (PUSLAPIS_2);
printf ('PADARYTA n');

grįžti 0;

}

test2.c (sistemos skambučiai)

#įtraukti
#įtraukti
#įtraukti
#įtraukti
#įtraukti
#įtraukti
#įtraukti
#įtraukti
#įtraukti

#define BUFFER_SIZE 67108864

tarptpagrindinis() {

tarptneteisingai,galas;

printf (' nĮvesties/išvesties testas su sendfile () ir susiję sistemos skambučiai. n n');

// Paimkite BUFFER_SIZE buferį.
// Buferyje bus atsitiktinių duomenų, bet mums tai nerūpi.
printf („Skiriamas 64 MB buferis:“);
anglis *buferis= (anglis *) malloc (BUFFER_SIZE);
printf ('PADARYTA n');


// Įrašykite buferį į fOut
printf („Duomenų įrašymas į pirmąjį buferį:“);
neteisingai=atviras('buferis1',O_RDONLY);
rašyti(neteisingai, &buferis,BUFFER_SIZE);
Uždaryti(neteisingai);
printf ('PADARYTA n');

printf („Duomenų kopijavimas iš pirmo failo į antrą:“);
galas=atviras('buferis1',O_RDONLY);
neteisingai=atviras(„buferis2“,O_RDONLY);
Siųsti failą(neteisingai,galas, 0,BUFFER_SIZE);
Uždaryti(galas);
Uždaryti(neteisingai);
printf ('PADARYTA n');

printf ('Išlaisvinamas buferis:');
Laisvas (buferis);
printf ('PADARYTA n');

printf („Failų trynimas“:);
atsieti('buferis1');
atsieti(„buferis2“);
printf ('PADARYTA n');

grįžti 0;

}

1 ir 2 testų sudarymas ir vykdymas

Norėdami sukurti šiuos pavyzdžius, jums reikės jūsų platinime įdiegtų kūrimo įrankių. „Debian“ ir „Ubuntu“ galite tai įdiegti naudodami:

tinkamasdiegtipagrindiniai dalykai

Tada sudarykite naudodami:

gcctest1.c-arbatestas1&& gcctest2.c-arbatestas2

Norėdami paleisti abu ir patikrinti našumą, paleiskite:

laikas./testas1&& laikas./testas2

Turėtumėte gauti tokius rezultatus:

Įvesties/išvesties testas su tradicinėmis „glibc“ funkcijomis.

64 MB buferio paskyrimas: ATLIKTA
Duomenų įrašymas į pirmąjį buferį: ATLIKTA
Duomenų kopijavimas iš pirmo failo į antrą: ATLIKTA
Atlaisvinamasis buferis: ATLIKTA
Failų trynimas: ATLIKTA
tikras 0m0.397s
vartotojas 0 mln
sys 0m0.203s
Įvesties/išvesties testas su sendfile () ir susiję sistemos skambučiai.
64 MB buferio paskyrimas: ATLIKTA
Duomenų įrašymas į pirmąjį buferį: ATLIKTA
Duomenų kopijavimas iš pirmo failo į antrą: ATLIKTA
Atlaisvinamasis buferis: ATLIKTA
Failų trynimas: ATLIKTA
tikras 0m0.019s
vartotojas 0 mln
sys 0m0.016s

Kaip matote, kodas, kuris naudoja sistemos skambučius, veikia daug greičiau nei „glibc“ atitikmuo.

Dalykai, kuriuos reikia prisiminti

Sisteminiai skambučiai gali padidinti našumą ir suteikti papildomų funkcijų, tačiau jie nėra be trūkumų. Turėsite pasverti sistemos skambučių teikiamą naudą, palyginti su platformos perkeliamumo trūkumu ir kartais sumažėjusiu funkcionalumu, palyginti su bibliotekos funkcijomis.

Kai naudojate kai kuriuos sistemos skambučius, turite pasirūpinti, kad būtų naudojami ištekliai, gauti iš sistemos skambučių, o ne bibliotekos funkcijos. Pvz., FILE struktūra, naudojama „glibc“ fopen (), fread (), fwrite () ir fclose () funkcijoms, nėra ta pati kaip failo aprašymo numeris iš atviro () sistemos iškvietimo (grąžinamas kaip sveikasis skaičius). Jų maišymas gali sukelti problemų.

Apskritai, „Linux“ sistemos skambučiai turi mažiau buferio juostų nei „glibc“ funkcijos. Nors tiesa, kad sistemos skambučiai turi tam tikrą klaidų tvarkymą ir ataskaitų teikimą, iš „glibc“ funkcijos gausite išsamesnes funkcijas.

Ir pabaigai - žodis apie saugumą. Sistemos skambučiai tiesiogiai sąveikauja su branduoliu. „Linux“ branduolys turi visapusišką apsaugą nuo klaidinimų iš vartotojo šalies, tačiau yra neatrastų klaidų. Nesitikėkite, kad sistemos skambutis patvirtins jūsų įvestį arba izoliuos jus nuo saugumo problemų. Išmintinga užtikrinti, kad sistemos skambučiui perduoti duomenys būtų dezinfekuoti. Natūralu, kad tai yra geras patarimas bet kokiam API skambučiui, tačiau dirbdami su branduoliu negalite būti atsargūs.

Tikiuosi, kad jums patiko šis gilesnis pasinėrimas į „Linux“ sistemos skambučių šalį. Išsamų „Linux“ sistemos skambučių sąrašą rasite mūsų pagrindiniame sąraše.