Unix හි නල මාර්ග ක්රියාත්මක වන ආකාරය

Unix හි නල මාර්ග ක්රියාත්මක වන ආකාරය
මෙම ලිපිය Unix කර්නලයේ නල මාර්ග ක්රියාත්මක කිරීම විස්තර කරයි. " යන මාතෘකාව යටතේ මෑතකදී පළ වූ ලිපියක් ගැන මම තරමක් කලකිරුණා.Unix හි නල මාර්ග ක්‍රියා කරන්නේ කෙසේද?"හැරුණා නෑ අභ්යන්තර ව්යුහය ගැන. මම කුතුහලයට පත් වූ අතර පිළිතුර සොයා ගැනීමට පැරණි මූලාශ්‍ර හාරා බැලුවෙමි.

අපි කතා කරන්නේ කුමක් ගැනද?

නල මාර්ග, “සමහරවිට Unix හි ඇති වැදගත්ම සොයාගැනීම”, කුඩා වැඩසටහන් එකට සම්බන්ධ කිරීමේ යටින් පවතින Unix දර්ශනයේ නිර්වචන ලක්ෂණයක් මෙන්ම විධාන රේඛාවේ හුරුපුරුදු ලකුණකි:

$ echo hello | wc -c
6

මෙම ක්‍රියාකාරීත්වය කර්නලය සපයන පද්ධති ඇමතුම මත රඳා පවතී pipe, ලේඛන පිටුවල විස්තර කර ඇත නල (7) и නල (2):

අන්තර් ක්‍රියාවලි සන්නිවේදනය සඳහා නල මාර්ග ඒක දිශානුගත නාලිකාවක් සපයයි. නල මාර්ගයේ ආදානය (ලියන අවසානය) සහ ප්රතිදානය (කියවීම අවසානය) ඇත. නල මාර්ගයේ ආදානයට ලියන ලද දත්ත ප්රතිදානයේදී කියවිය හැක.

නල මාර්ගය නිර්මාණය කර ඇත්තේ ඇමතුම භාවිතා කරමිනි pipe(2), එය ගොනු විස්තර දෙකක් ලබා දෙයි: එකක් නල මාර්ගයේ ආදානයට යොමු කරයි, දෙවැන්න ප්‍රතිදානය වෙත යොමු කරයි.

ඉහත විධානයෙන් ලැබෙන ට්‍රේස් ප්‍රතිදානය මඟින් නල මාර්ගය නිර්මාණය කිරීම සහ එය හරහා එක් ක්‍රියාවලියකින් තවත් ක්‍රියාවලියකට දත්ත ගලායාම පෙන්වයි:

$ strace -qf -e execve,pipe,dup2,read,write 
    sh -c 'echo hello | wc -c'

execve("/bin/sh", ["sh", "-c", "echo hello | wc -c"], …)
pipe([3, 4])                            = 0
[pid 2604795] dup2(4, 1)                = 1
[pid 2604795] write(1, "hellon", 6)    = 6
[pid 2604796] dup2(3, 0)                = 0
[pid 2604796] execve("/usr/bin/wc", ["wc", "-c"], …)
[pid 2604796] read(0, "hellon", 16384) = 6
[pid 2604796] write(1, "6n", 2)        = 2

මාපිය ක්‍රියාවලිය අමතයි pipe()සවිකර ඇති ගොනු විස්තර ලබා ගැනීමට. එක් ළමා ක්‍රියාවලියක් එක් හසුරුවකට ලියන අතර තවත් ක්‍රියාවලියක් තවත් හසුරුවකින් එම දත්ත කියවයි. stdin සහ stdout වලට ගැලපෙන පරිදි විස්තර 2 සහ 3 "නැවත නම් කිරීමට" shell එක dup4 භාවිතා කරයි.

පයිප්ප නොමැතිව, කවචයට එක් ක්‍රියාවලියක ප්‍රති result ලය ගොනුවකට ලිවීමට සහ ගොනුවේ දත්ත කියවීමට එය වෙනත් ක්‍රියාවලියකට යැවීමට සිදුවේ. එහි ප්රතිඵලයක් වශයෙන්, අපි වැඩි සම්පත් හා තැටි ඉඩ නාස්ති කරනු ඇත. කෙසේ වෙතත්, නල මාර්ග හොඳ වන්නේ තාවකාලික ලිපිගොනු භාවිතය වළක්වා ගැනීමට ඒවා ඔබට ඉඩ සලසන නිසා පමණක් නොවේ:

ක්‍රියාවලියක් හිස් නල මාර්ගයකින් කියවීමට උත්සාහ කරන්නේ නම් read(2) දත්ත ලැබෙන තුරු අවහිර කරනු ඇත. ක්‍රියාවලියක් සම්පූර්ණ නල මාර්ගයකට ලිවීමට උත්සාහ කරන්නේ නම්, එසේ නම් write(2) ලිවීම සිදු කිරීමට ප්‍රමාණවත් දත්ත නල මාර්ගයෙන් කියවන තුරු අවහිර කරනු ඇත.

POSIX අවශ්‍යතාවය මෙන්, මෙය වැදගත් දේපලකි: දක්වා නල මාර්ගයට ලිවීම PIPE_BUF බයිට් (අවම වශයෙන් 512) පරමාණුක විය යුතු අතර එමඟින් සාමාන්‍ය ලිපිගොනු (එවැනි සහතික ලබා නොදෙන) ක්‍රියාවලීන්ට නල මාර්ගය හරහා එකිනෙකා සමඟ සන්නිවේදනය කළ හැකිය.

සාමාන්‍ය ගොනුවක් භාවිතා කරන විට, ක්‍රියාවලියකට එහි සියලුම ප්‍රතිදානය ලියා වෙනත් ක්‍රියාවලියකට එය ලබා දිය හැක. නැතහොත් ලිවීමක් හෝ කියවීමක් සම්පූර්ණ වූ විට එකිනෙකාට දැනුම් දීම සඳහා බාහිර සංඥා යාන්ත්‍රණයක් (සෙමාෆෝරයක් වැනි) භාවිතා කරමින් ක්‍රියාවලි ඉතා සමාන්තර ආකාරයෙන් ක්‍රියා කළ හැක. වාහකයන් මේ සියලු කරදරවලින් අපව ගලවා ගනී.

අපි සොයන්නේ කුමක් ද?

වාහකයක් ක්‍රියා කරන්නේ කෙසේදැයි ඔබට සිතීමට පහසු වන පරිදි මම එය සරල වචන වලින් පැහැදිලි කරමි. ඔබට මතකයේ බෆරයක් සහ යම් තත්වයක් වෙන් කිරීමට අවශ්‍ය වනු ඇත. බෆරයෙන් දත්ත එක් කිරීමට සහ ඉවත් කිරීමට ඔබට කාර්යයන් අවශ්‍ය වනු ඇත. ගොනු විස්තර සඳහා කියවීමේ සහ ලිවීමේ මෙහෙයුම් වලදී ශ්‍රිත ඇමතීමට ඔබට යම් ක්‍රම අවශ්‍ය වනු ඇත. තවද ඉහත විස්තර කර ඇති විශේෂ හැසිරීම ක්රියාත්මක කිරීම සඳහා ඔබට අගුල් අවශ්ය වනු ඇත.

දැන් අපි අපගේ නොපැහැදිලි මානසික ආකෘතිය තහවුරු කිරීමට හෝ ප්‍රතික්ෂේප කිරීමට දීප්තිමත් ලාම්පු එළිය යටතේ කර්නල් මූල කේතය ප්‍රශ්න කිරීමට සූදානම්ව සිටිමු. නමුත් අනපේක්ෂිත දේ සඳහා සැමවිටම සූදානම්ව සිටින්න.

අපි කොහෙද බලන්නේ?

මගේ සුප්‍රසිද්ධ පොතේ පිටපත කොහේදැයි මම නොදනිමි.සිංහ පොත"Unix 6 මූල කේතය සමඟ, නමුත් ස්තූතියි යුනික්ස් හෙරිටේජ් සමිතිය ඔබට සබැඳිව සෙවිය හැක ප්රභව කේතය Unix හි පවා පැරණි අනුවාද.

TUHS ලේඛනාගාරය හරහා සැරිසැරීම කෞතුකාගාරයක් නැරඹීමට සමාන ය. අපට අපගේ හවුල් ඉතිහාසය දෙස බැලිය හැකි අතර, පැරණි ටේප් සහ මුද්‍රණවලින් ටිකෙන් ටික මේ සියලු ද්‍රව්‍ය ප්‍රතිසාධනය කිරීමට වසර ගණනාවක් දරන උත්සාහයට මම ගරු කරමි. ඒ වගේම තවමත් අතුරුදහන්ව ඇති එම කොටස් ගැන මම හොඳින් දනිමි.

වාහකයන්ගේ පැරණි ඉතිහාසය පිළිබඳ අපගේ කුතුහලය තෘප්තිමත් කිරීමෙන්, සංසන්දනය කිරීම සඳහා අපට නවීන කර්නල් දෙස බැලිය හැකිය.

මාර්ගය වන විට, pipe මේසයේ පද්ධති ඇමතුම් අංක 42 වේ sysent[]. අහම්බයක්ද?

සම්ප්‍රදායික යුනික්ස් කර්නල් (1970-1974)

මම කිසිම හෝඩුවාවක් සොයා ගත්තේ නැහැ pipe(2) තුළ නැත PDP-7 Unix (ජනවාරි 1970), හෝ නැත Unix හි පළමු සංස්කරණය (නොවැම්බර් 1971), හෝ අසම්පූර්ණ මූල කේතයේ නැත දෙවන සංස්කරණය (ජුනි 1972).

TUHS සඳහන් කරයි Unix තුන්වන සංස්කරණය (පෙබරවාරි 1973) වාහක සහිත පළමු අනුවාදය බවට පත් විය:

Unix 1973rd Edition යනු එකලස් කිරීමේ භාෂාවෙන් ලියා ඇති කර්නලයක් සහිත අවසාන අනුවාදය වන අතර නල මාර්ග සහිත පළමු අනුවාදය ද විය. XNUMX දී, තුන්වන සංස්කරණය වැඩිදියුණු කිරීම සඳහා කටයුතු සිදු කරන ලදී, කර්නලය C වලින් නැවත ලියන ලද අතර, එබැවින් Unix හි සිව්වන සංස්කරණය දර්ශනය විය.

එක් පාඨකයෙකු විසින් Doug McIlroy විසින් "උද්යාන හෝස් වැනි වැඩසටහන් සම්බන්ධ කිරීම" පිළිබඳ අදහස යෝජනා කළ ලේඛනයක ස්කෑන් පරීක්ෂණයක් සොයා ගන්නා ලදී.

Unix හි නල මාර්ග ක්රියාත්මක වන ආකාරය
Brian Kernighan ගේ පොතේUnix: ඉතිහාසය සහ මතක සටහන්", වාහක මතුවීමේ ඉතිහාසයේ, මෙම ලේඛනය ද සඳහන් වේ: "... එය වසර 30 ක් තිස්සේ බෙල් ලැබ්ස් හි මගේ කාර්යාලයේ බිත්තියේ එල්ලා තිබේ." මෙතන මැක්ල්රෝයි සමඟ සම්මුඛ සාකච්ඡාවක්, සහ තවත් කතාවක් මැක්ල්රෝයිගේ කෘතිය, 2014 දී ලියා ඇත:

Unix පිටතට පැමිණි විට, coroutines සඳහා වූ මගේ ඇල්ම නිසා, OS හි කර්තෘ Ken Thompson ගෙන්, ක්‍රියාවලියකට ලියා ඇති දත්ත උපාංගයට පමණක් නොව, වෙනත් ක්‍රියාවලියකට ප්‍රතිදානය කිරීමට ඉඩ දෙන ලෙස ඉල්ලා සිටීමට මට හේතු විය. එය කළ හැකි බව කෙන් තීරණය කළේය. කෙසේ වෙතත්, අවමවාදී ලෙස, සෑම පද්ධති කාර්යයක්ම සැලකිය යුතු කාර්යභාරයක් ඉටු කිරීමට ඔහුට අවශ්‍ය විය. ක්‍රියාවලි අතර කෙලින්ම ලිවීම අතරමැදි ගොනුවකට ලිවීමට වඩා විශාල වාසියක්ද? "පයිප්ලයින්" යන ආකර්ශනීය නම සහ ක්‍රියාවලීන් අතර අන්තර්ක්‍රියා සඳහා වාක්‍ය ඛණ්ඩය පිළිබඳ විස්තරයක් සහිත නිශ්චිත යෝජනාවක් මා විසින් ඉදිරිපත් කළ විට පමණක් කෙන් අවසානයේ ප්‍රකාශ කළේය: "මම එය කරන්නම්!"

සහ කළා. එක් දෛවෝපගත සන්ධ්‍යාවක්, කෙන් කර්නලය සහ කවචය වෙනස් කළේය, ඔවුන් ආදානය පිළිගන්නා ආකාරය (නල මාර්ගයකින් පැමිණිය හැකි) ප්‍රමිතිගත කිරීම සඳහා සම්මත වැඩසටහන් කිහිපයක් සවි කළේය, සහ ගොනු නාම ද වෙනස් කළේය. ඊළඟ දවසේ, නල මාර්ග යෙදුම්වල ඉතා පුළුල් ලෙස භාවිතා කිරීමට පටන් ගත්තේය. සතිය අවසන් වන විට, ලේකම්වරු වර්ඩ් ප්‍රොසෙසර වලින් ලේඛන මුද්‍රණ යන්ත්‍රයට යැවීමට ඒවා භාවිතා කළහ. මඳ වේලාවකට පසු, කෙන් විසින් නල මාර්ග භාවිතය පිරිසිදු සම්මුතීන් සමඟ එතීමට මුල් API සහ වාක්‍ය ඛණ්ඩය ප්‍රතිස්ථාපනය කරන ලද අතර එය එතැන් සිට භාවිතා වේ.

අවාසනාවකට, Unix කර්නලයේ තුන්වන සංස්කරණය සඳහා වූ මූල කේතය නැති වී ඇත. C වලින් ලියා ඇති කර්නල් ප්‍රභව කේතය අප සතුව ඇතත් හතරවන සංස්කරණය, 1973 නොවැම්බර් මාසයේදී නිකුත් කරන ලද නමුත් එය නිල නිකුතුවට මාස කිහිපයකට පෙර නිකුත් වූ අතර නල මාර්ග ක්රියාත්මක කිරීම් අඩංගු නොවේ. මෙම ජනප්‍රිය Unix ශ්‍රිතයේ මූල කේතය සමහර විට සදහටම නැතිවී යාම ලැජ්ජාවකි.

සඳහා පෙළ ලේඛන අප සතුව ඇත pipe(2) නිකුතු දෙකෙන්ම, ඔබට ලේඛන සෙවීමෙන් ආරම්භ කළ හැක තෙවන සංස්කරණය (ඇතැම් වචන සඳහා, "අතින්" යටින් ඉරි ඇඳ ඇති, ^H අක්ෂර මාලාවක්, පසුව යටි ඉරක්!). මෙම මූලාකෘතිය -pipe(2) එකලස් කිරීමේ භාෂාවෙන් ලියා ඇති අතර එක් ගොනු විස්තරයක් පමණක් ආපසු ලබා දෙයි, නමුත් දැනටමත් අපේක්ෂිත මූලික ක්‍රියාකාරීත්වය සපයයි:

පද්ධති ඇමතුම නළයයි නල මාර්ගයක් ලෙස හැඳින්වෙන ආදාන/ප්‍රතිදාන යාන්ත්‍රණයක් නිර්මාණය කරයි. ආපසු ලබා දුන් ගොනු විස්තරය කියවීම සහ ලිවීමේ මෙහෙයුම් සඳහා භාවිතා කළ හැක. නල මාර්ගයට යමක් ලියා ඇති විට, දත්ත බයිට් 504 ක් දක්වා බෆර කරනු ලැබේ, පසුව ලිවීමේ ක්‍රියාවලිය අත්හිටුවනු ලැබේ. නල මාර්ගයෙන් කියවන විට, ස්වාරක්ෂක දත්ත ඉවත් කරනු ලැබේ.

ඊළඟ වසර වන විට කර්නලය C වලින් නැවත ලියා ඇත, සහ පයිප්ප (2) සිව්වන සංස්කරණයේ මූලාකෘතිය සමඟ එහි නවීන පෙනුම ලබා ගත්තේය "pipe(fildes)»:

පද්ධති ඇමතුම නළයයි නල මාර්ගයක් ලෙස හැඳින්වෙන ආදාන/ප්‍රතිදාන යාන්ත්‍රණයක් නිර්මාණය කරයි. ආපසු ලබා දුන් ගොනු විස්තර කියවීම සහ ලිවීමේ මෙහෙයුම් වලදී භාවිතා කළ හැක. නල මාර්ගයට යමක් ලියා ඇති විට, r1 (resp. fildes[1]) හි ආපසු ලබා දුන් හසුරුව භාවිතා කරනු ලැබේ, දත්ත බයිට් 4096 දක්වා බෆර කර, පසුව ලිවීමේ ක්‍රියාවලිය අත්හිටුවනු ලැබේ. නල මාර්ගයෙන් කියවන විට, හසුරුව r0 වෙත ආපසු (resp. fildes[0]) දත්ත ලබා ගනී.

නල මාර්ගයක් නිර්වචනය කළ පසු, සන්නිවේදන ක්‍රියාවලි දෙකක් (හෝ වැඩි ගණනක්) (පසුකාලීන ඇමතුම් මගින් සාදනු ලැබේ) යැයි උපකල්පනය කෙරේ. දෙබස්) ඇමතුම් භාවිතයෙන් නල මාර්ගයෙන් දත්ත මාරු කරනු ඇත කියවන්න и ලියන්න.

නල මාර්ගයකින් සම්බන්ධ වූ රේඛීය ක්‍රියාවලි මාලාවක් නිර්වචනය කිරීම සඳහා කවචයට වාක්‍ය ඛණ්ඩයක් ඇත.

එක් කෙළවරක් පමණක් ඇති (සියලුම ලිවීමේ ගොනු විස්තර වසා ඇත) හිස් නල මාර්ගයකින් කියවීමට ඇමතුම් "ගොනුවේ අවසානය" ලබා දෙයි. සමාන තත්වයක් තුළ ලිවීමට ඇමතුම් නොසලකා හරිනු ලැබේ.

කලින්ම සංරක්ෂිත නල මාර්ග ක්රියාත්මක කිරීම අදාළ වේ Unix පස්වන සංස්කරණයට (ජූනි 1974), නමුත් එය ඊළඟ නිකුතුවේ දර්ශනය වූ එකට බොහෝ දුරට සමාන වේ. අදහස් දැන් එකතු කර ඇත, එබැවින් ඔබට පස්වන සංස්කරණය මඟ හැරිය හැක.

Unix හි හයවන සංස්කරණය (1975)

අපි Unix මූල කේතය කියවීමට පටන් ගනිමු හයවන සංස්කරණය (1975 මැයි). බොහෝ දුරට ස්තුතියි සිංහ පෙර අනුවාද වල මූලාශ්‍රවලට වඩා සොයා ගැනීම ඉතා පහසු ය:

වසර ගණනාවක් පොත සිංහ Bell Labs වලින් පිටත Unix කර්නලයේ ඇති එකම ලේඛනය විය. හයවන මුද්‍රණ බලපත්‍රය ගුරුවරුන්ට එහි මූල කේතය භාවිතා කිරීමට ඉඩ දුන්නද, හත්වන සංස්කරණයේ බලපත්‍රය මෙම හැකියාව බැහැර කර ඇත, එබැවින් පොත බෙදා හරින ලද්දේ නීති විරෝධී ටයිප් කරන ලද පිටපත් ආකාරයෙන්ය.

අද ඔබට පොතේ නැවත මුද්‍රණයක් මිලදී ගත හැකි අතර, එහි කවරය සිසුන්ට පිටපත් යන්ත්‍රයක පෙන්වයි. සහ වොරන් ටූමිට (TUHS ව්‍යාපෘතිය ආරම්භ කළ) ස්තූතියි ඔබට බාගත හැකිය හයවන සංස්කරණය සඳහා මූලාශ්‍ර කේතය සහිත PDF ගොනුව. ගොනුව සෑදීමට කොපමණ උත්සාහයක් දැරුවද යන්න පිළිබඳ අදහසක් ඔබට ලබා දීමට මට අවශ්‍යය:

මීට වසර 15 කට පෙර, මම ලබා දී ඇති මූලාශ්‍ර කේතයේ පිටපතක් ටයිප් කළෙමි සිංහ, නොදන්නා වෙනත් පිටපත් ගණනකින් මගේ පිටපතේ ගුණාත්මක භාවයට මා අකමැති වූ නිසා. TUHS තවමත් නොතිබූ අතර මට පැරණි මූලාශ්‍ර වෙත ප්‍රවේශය නොතිබුණි. නමුත් 1988 දී, මම PDP9 පරිගණකයකින් උපස්ථයක් අඩංගු පැරණි ධාවන පථ 11 ටේප් එකක් සොයාගත්තා. එය ක්‍රියාත්මක වේද යන්න කීමට අපහසු වූ නමුත් බොහෝ ලිපිගොනු 1979 වසර ලෙස ලේබල් කර තිබූ /usr/src/ ගසක් තිබූ අතර එය එදත් පැරණි බව පෙනේ. එය මා විශ්වාස කළ පරිදි හත්වන සංස්කරණය හෝ එහි ව්‍යුත්පන්න PWB විය.

මම සොයා ගැනීම පදනමක් ලෙස ගෙන හයවන සංස්කරණයට මූලාශ්‍ර අතින් සංස්කරණය කළෙමි. සමහර කේතයන් එලෙසම පැවතුන නමුත් සමහර ඒවා තරමක් සංස්කරණය කිරීමට සිදු විය, නවීන += ටෝකනය යල් පැන ගිය =+ ලෙස වෙනස් කර ඇත. සමහර දේවල් සරලව මකා දැමූ අතර සමහර ඒවා සම්පූර්ණයෙන්ම නැවත ලිවිය යුතු නමුත් වැඩි නොවේ.

අද අපට TUHS හි හයවන සංස්කරණයේ මූල කේතය මාර්ගගතව කියවිය හැකිය ලේඛනාගාරය, ඩෙනිස් රිචීට අත තිබුනා.

මාර්ගය වන විට, මුලින්ම බැලූ බැල්මට, කර්නිගන් සහ රිචීගේ කාලයට පෙර C-කේතයේ ප්රධාන ලක්ෂණය වන්නේ එහි ය. කෙටිකතාව. මගේ වෙබ් අඩවියේ සාපේක්ෂව පටු සංදර්ශක ප්‍රදේශයකට සරිලන පරිදි පුළුල් සංස්කරණයකින් තොරව කේත කොටස් ඇතුළු කිරීමට මට හැකි වන්නේ බොහෝ විට නොවේ.

ආරම්භයේ දී /usr/sys/ken/pipe.c පැහැදිලි කිරීමේ විවරණයක් ඇත (සහ ඔව්, තවත් ඇත /usr/sys/dmr):

/*
 * Max allowable buffering per pipe.
 * This is also the max size of the
 * file created to implement the pipe.
 * If this size is bigger than 4096,
 * pipes will be implemented in LARG
 * files, which is probably not good.
 */
#define    PIPSIZ    4096

සිව්වන සංස්කරණයේ සිට බෆරයේ ප්‍රමාණය වෙනස් වී නොමැත. නමුත් මෙහිදී අපට පෙනෙන්නේ, කිසිදු පොදු ලියකියවිලි නොමැතිව, නල මාර්ග වරක් ගොනු උපස්ථ ගබඩාව ලෙස භාවිතා කළ බවයි!

LARG ගොනු සඳහා, ඒවා අනුරූප වේ ඉනෝඩ් ධජය විශාලයි, එය සැකසීමට "විශාල ලිපින ඇල්ගොරිතම" මගින් භාවිතා කරයි වක්ර කුට්ටි විශාල ගොනු පද්ධති සඳහා සහය දැක්වීමට. ඒවා පාවිච්චි නොකර ඉන්න එක හොඳයි කියලා කෙන් කිව්ව නිසා මම එයාගේ වචනය සතුටින් බාරගන්නම්.

මෙන්න නියම සිස්ටම් කෝල් එක pipe:

/*
 * The sys-pipe entry.
 * Allocate an inode on the root device.
 * Allocate 2 file structures.
 * Put it all together with flags.
 */
pipe()
{
    register *ip, *rf, *wf;
    int r;

    ip = ialloc(rootdev);
    if(ip == NULL)
        return;
    rf = falloc();
    if(rf == NULL) {
        iput(ip);
        return;
    }
    r = u.u_ar0[R0];
    wf = falloc();
    if(wf == NULL) {
        rf->f_count = 0;
        u.u_ofile[r] = NULL;
        iput(ip);
        return;
    }
    u.u_ar0[R1] = u.u_ar0[R0]; /* wf's fd */
    u.u_ar0[R0] = r;           /* rf's fd */
    wf->f_flag = FWRITE|FPIPE;
    wf->f_inode = ip;
    rf->f_flag = FREAD|FPIPE;
    rf->f_inode = ip;
    ip->i_count = 2;
    ip->i_flag = IACC|IUPD;
    ip->i_mode = IALLOC;
}

කමෙන්ට් එකේ මෙතන වෙන්නේ මොකක්ද කියලා පැහැදිලිව විස්තර කරනවා. නමුත් කේතය තේරුම් ගැනීම එතරම් පහසු නැත, අර්ධ වශයෙන් මාර්ගය නිසා "struct user u» සහ ලියාපදිංචි වේ R0 и R1 පද්ධති ඇමතුම් පරාමිතීන් සහ ප්‍රතිලාභ අගයන් සම්මත වේ.

අපි සමඟ උත්සාහ කරමු ialloc () තැටිය මත තබා ඉනෝඩය (දර්ශක හසුරුව), සහ උපකාරයෙන් falloc () - දෙකක් මතකයේ තබන්න ගොනුව. සියල්ල හොඳින් සිදුවුවහොත්, අපි මෙම ගොනු නල මාර්ගයේ කෙළවර දෙකක් ලෙස හඳුනා ගැනීමට කොඩි සකසන්නෙමු, ඒවා එකම ඉනෝඩයට යොමු කරන්න (එහි යොමු ගණන 2 ලෙස සකසා ඇත), සහ ඉනෝඩය වෙනස් කළ සහ භාවිතයේ පවතින ලෙස සලකුණු කරන්න. ඉල්ලීම් කෙරෙහි අවධානය යොමු කරන්න මම තැබුවා() නව ඉනෝඩයේ සමුද්දේශ ගණන අඩු කිරීමට දෝෂ සහිත මාර්ග.

pipe() හරහා විය යුතුය R0 и R1 කියවීම සහ ලිවීම සඳහා ගොනු විස්තර අංක ආපසු දෙන්න. falloc() ගොනු ව්‍යුහයට දර්ශකයක් ආපසු ලබා දෙයි, නමුත් හරහා "ආපසු" ද ලබා දෙයි u.u_ar0[R0] සහ ගොනු විස්තරයක්. එනම්, කේතය සුරකියි r කියවීම සඳහා ගොනු විස්තරකය සහ සෘජුවම ලිවීම සඳහා ගොනු විස්තරයක් පවරයි u.u_ar0[R0] දෙවන ඇමතුමෙන් පසුව falloc().

ධජය FPIPE, නල මාර්ගය නිර්මාණය කිරීමේදී අප විසින් සකස් කරන ලද, කාර්යයේ හැසිරීම පාලනය කරයි rdwr() in sys2.cවිශේෂිත I/O චර්යාවන් ඇමතීම:

/*
 * common code for read and write calls:
 * check permissions, set base, count, and offset,
 * and switch out to readi, writei, or pipe code.
 */
rdwr(mode)
{
    register *fp, m;

    m = mode;
    fp = getf(u.u_ar0[R0]);
        /* … */

    if(fp->f_flag&FPIPE) {
        if(m==FREAD)
            readp(fp); else
            writep(fp);
    }
        /* … */
}

එවිට කාර්යය readp() в pipe.c නල මාර්ගයෙන් දත්ත කියවයි. නමුත් සිට ක්රියාත්මක කිරීම ආරම්භ කිරීම වඩා හොඳය writep(). නැවතත්, තර්ක සම්මත කිරීමේ සම්මුතීන් හේතුවෙන් කේතය වඩාත් සංකීර්ණ වී ඇත, නමුත් සමහර විස්තර මඟ හැරිය හැක.

writep(fp)
{
    register *rp, *ip, c;

    rp = fp;
    ip = rp->f_inode;
    c = u.u_count;

loop:
    /* If all done, return. */

    plock(ip);
    if(c == 0) {
        prele(ip);
        u.u_count = 0;
        return;
    }

    /*
     * If there are not both read and write sides of the
     * pipe active, return error and signal too.
     */

    if(ip->i_count < 2) {
        prele(ip);
        u.u_error = EPIPE;
        psignal(u.u_procp, SIGPIPE);
        return;
    }

    /*
     * If the pipe is full, wait for reads to deplete
     * and truncate it.
     */

    if(ip->i_size1 == PIPSIZ) {
        ip->i_mode =| IWRITE;
        prele(ip);
        sleep(ip+1, PPIPE);
        goto loop;
    }

    /* Write what is possible and loop back. */

    u.u_offset[0] = 0;
    u.u_offset[1] = ip->i_size1;
    u.u_count = min(c, PIPSIZ-u.u_offset[1]);
    c =- u.u_count;
    writei(ip);
    prele(ip);
    if(ip->i_mode&IREAD) {
        ip->i_mode =& ~IREAD;
        wakeup(ip+2);
    }
    goto loop;
}

නල මාර්ග ආදානයට බයිට් ලිවීමට අපට අවශ්‍යයි u.u_count. මුලින්ම අපි ඉනෝඩය අගුළු දැමිය යුතුයි (පහත බලන්න plock/prele).

ඊට පස්සේ අපි inode reference counter එක පරීක්ෂා කරනවා. නල මාර්ගයේ කෙළවර දෙකම විවෘතව පවතින තාක් කල්, කවුන්ටරය 2 ට සමාන විය යුතුය. අපි එක් සබැඳියක් අල්ලාගෙන සිටිමු (සිට rp->f_inode), එබැවින් කවුන්ටරය 2 ට වඩා අඩු නම්, එය කියවීමේ ක්රියාවලිය නල මාර්ගයේ එහි අවසානය වසා ඇති බව අදහස් විය යුතුය. වෙනත් වචන වලින් කිවහොත්, අපි සංවෘත නල මාර්ගයකට ලිවීමට උත්සාහ කරන අතර මෙය දෝෂයකි. පළමු වරට දෝෂ කේතය EPIPE සහ සංඥාව SIGPIPE Unix හි හයවන සංස්කරණයේ පෙනී සිටියේය.

නමුත් වාහකය විවෘත වුවද, එය පිරී තිබිය හැක. මෙම අවස්ථාවේ දී, අපි අගුල මුදා හැර නින්දට යන්නේ තවත් ක්රියාවලියක් නල මාර්ගයෙන් කියවා එහි ප්රමාණවත් ඉඩක් නිදහස් කරනු ඇතැයි යන බලාපොරොත්තුවෙන් ය. අවදි වූ පසු, අපි නැවත ආරම්භයට පැමිණ, අගුල නැවත එල්ලා නව පටිගත කිරීමේ චක්‍රයක් ආරම්භ කරමු.

නල මාර්ගයේ ප්රමාණවත් නිදහස් ඉඩක් තිබේ නම්, අපි එය භාවිතා කරමින් දත්ත ලියන්නෙමු ලියන්න (). පරාමිතිය i_size1 inode හි (නල මාර්ගය හිස් නම් එය 0 ට සමාන විය හැක) එය දැනටමත් අඩංගු දත්තවල අවසානය පෙන්නුම් කරයි. ප්‍රමාණවත් පටිගත කිරීමේ ඉඩක් තිබේ නම්, අපට නල මාර්ගයෙන් පිරවිය හැකිය i_size1 කිරීමට PIPESIZ. ඉන්පසුව අපි අගුල මුදා හැර නල මාර්ගයේ සිට කියවීමට බලා සිටින ඕනෑම ක්රියාවලියක් අවදි කිරීමට උත්සාහ කරමු. අපට අවශ්‍ය තරම් බයිට් ප්‍රමාණයක් ලිවීමට අපට හැකි වූවාද යන්න බැලීමට අපි නැවත මුලට යමු. එය අසාර්ථක වුවහොත්, අපි නව පටිගත කිරීමේ චක්රයක් ආරම්භ කරමු.

සාමාන්යයෙන් පරාමිතිය i_mode inode අවසර ගබඩා කිරීමට භාවිතා කරයි r, w и x. නමුත් නල මාර්ග සම්බන්ධයෙන්, අපි යම් ක්රියාවලියක් බිටු භාවිතයෙන් ලිවීමක් හෝ කියවීමක් බලා සිටින බවට සංඥා කරමු IREAD и IWRITE පිළිවෙලින්. ක්රියාවලිය ධජය සහ ඇමතුම් සකසයි sleep(), සහ අනාගතයේ දී වෙනත් ක්‍රියාවලියකට හේතු වනු ඇතැයි අපේක්ෂා කෙරේ wakeup().

සැබෑ මායාව සිදු වන්නේ එහි ය sleep() и wakeup(). තුළ ඒවා ක්රියාත්මක වේ slp.c, සුප්‍රසිද්ධ "ඔබ මෙය තේරුම් ගැනීමට බලාපොරොත්තු නොවේ" යන ප්‍රකාශයේ මූලාශ්‍රය. වාසනාවකට මෙන්, අපට කේතය තේරුම් ගැනීමට අවශ්‍ය නැත, සමහර අදහස් දෙස බලන්න:

/*
 * Give up the processor till a wakeup occurs
 * on chan, at which time the process
 * enters the scheduling queue at priority pri.
 * The most important effect of pri is that when
 * pri<0 a signal cannot disturb the sleep;
 * if pri>=0 signals will be processed.
 * Callers of this routine must be prepared for
 * premature return, and check that the reason for
 * sleeping has gone away.
 */
sleep(chan, pri) /* … */

/*
 * Wake up all processes sleeping on chan.
 */
wakeup(chan) /* … */

හේතු වන ක්රියාවලිය sleep() යම් නාලිකාවක් සඳහා, පසුව වෙනත් ක්‍රියාවලියක් මගින් අවදි විය හැක, එය හේතු වනු ඇත wakeup() එකම නාලිකාව සඳහා. writep() и readp() එවැනි යුගල ඇමතුම් හරහා ඔවුන්ගේ ක්‍රියාවන් සම්බන්ධීකරණය කරන්න. එය සටහන් කර ගන්න pipe.c සෑම විටම ප්රමුඛත්වය ලබා දෙයි PPIPE ඇමතූ විට sleep(), ඉතින් එච්චරයි sleep() සංඥාවකින් බාධා විය හැක.

දැන් අපට කාර්යය තේරුම් ගැනීමට සෑම දෙයක්ම තිබේ readp():

readp(fp)
int *fp;
{
    register *rp, *ip;

    rp = fp;
    ip = rp->f_inode;

loop:
    /* Very conservative locking. */

    plock(ip);

    /*
     * If the head (read) has caught up with
     * the tail (write), reset both to 0.
     */

    if(rp->f_offset[1] == ip->i_size1) {
        if(rp->f_offset[1] != 0) {
            rp->f_offset[1] = 0;
            ip->i_size1 = 0;
            if(ip->i_mode&IWRITE) {
                ip->i_mode =& ~IWRITE;
                wakeup(ip+1);
            }
        }

        /*
         * If there are not both reader and
         * writer active, return without
         * satisfying read.
         */

        prele(ip);
        if(ip->i_count < 2)
            return;
        ip->i_mode =| IREAD;
        sleep(ip+2, PPIPE);
        goto loop;
    }

    /* Read and return */

    u.u_offset[0] = 0;
    u.u_offset[1] = rp->f_offset[1];
    readi(ip);
    rp->f_offset[1] = u.u_offset[1];
    prele(ip);
}

ඔබට මෙම කාර්යය පහළ සිට ඉහළට කියවීම පහසු විය හැක. නල මාර්ගයේ යම් දත්තයක් ඇති විට "කියවීම සහ ආපසු" ශාඛාව සාමාන්යයෙන් භාවිතා වේ. මෙම අවස්ථාවේදී, අපි භාවිතා කරමු readi() අපි දැනට පවතින දත්ත වලින් පටන් ගෙන ලබා ගත හැකි තරම් දත්ත කියවමු f_offset කියවීම, පසුව අදාළ ඕෆ්සෙට් අගය යාවත්කාලීන කරන්න.

පසුව කියවීමේදී, කියවීමේ ඕෆ්සෙට් වෙත ළඟා වී ඇත්නම් නල මාර්ගය හිස් වනු ඇත i_size1 inode දී. අපි ස්ථානය 0 වෙත නැවත සකස් කර නල මාර්ගයට ලිවීමට අවශ්‍ය ඕනෑම ක්‍රියාවලියක් අවදි කිරීමට උත්සාහ කරමු. වාහකය පිරී ඇති විට, බව අපි දනිමු. writep() මත නින්දට වැටෙනු ඇත ip+1. දැන් නල මාර්ගය හිස් බැවින්, එහි ලිවීමේ චක්‍රය නැවත ආරම්භ කිරීමට අපට එය අවදි කළ හැක.

ඔබට කියවීමට කිසිවක් නොමැති නම්, එවිට readp() කොඩියක් සැකසිය හැක IREAD සහ නිදාගන්න ip+2. ඔහු අවදි කරන්නේ කුමක් දැයි අපි දනිමු writep(), එය නල මාර්ගයට සමහර දත්ත ලියන විට.

වෙත අදහස් readi() සහ writei() " හරහා පරාමිති පසු කිරීම වෙනුවට එය තේරුම් ගැනීමට ඔබට උපකාර වනු ඇතu"අපට ඒවා සාමාන්‍ය I/O ශ්‍රිතයන් ලෙස සැලකිය හැකි අතර එය ගොනුවක්, පිහිටුමක්, මතකයේ බෆරයක් ගෙන, කියවීමට හෝ ලිවීමට බයිට් ගණන ගණන් කරයි.

/*
 * Read the file corresponding to
 * the inode pointed at by the argument.
 * The actual read arguments are found
 * in the variables:
 *    u_base        core address for destination
 *    u_offset    byte offset in file
 *    u_count        number of bytes to read
 *    u_segflg    read to kernel/user
 */
readi(aip)
struct inode *aip;
/* … */

/*
 * Write the file corresponding to
 * the inode pointed at by the argument.
 * The actual write arguments are found
 * in the variables:
 *    u_base        core address for source
 *    u_offset    byte offset in file
 *    u_count        number of bytes to write
 *    u_segflg    write to kernel/user
 */
writei(aip)
struct inode *aip;
/* … */

"කොන්සර්වේටිව්" අවහිර කිරීම සම්බන්ධයෙන්, එසේ නම් readp() и writep() ඔවුන් තම කාර්යය අවසන් කරන තුරු හෝ ප්‍රතිඵලයක් ලැබෙන තුරු inode අවහිර කරන්න (එනම්, අමතන්න wakeup). plock() и prele() සරලව වැඩ කරන්න: වෙනස් ඇමතුම් කට්ටලයක් භාවිතා කිරීම sleep и wakeup අප විසින් මුදා හරින ලද අගුල අවශ්‍ය ඕනෑම ක්‍රියාවලියක් අවදි කිරීමට අපට ඉඩ දෙන්න:

/*
 * Lock a pipe.
 * If its already locked, set the WANT bit and sleep.
 */
plock(ip)
int *ip;
{
    register *rp;

    rp = ip;
    while(rp->i_flag&ILOCK) {
        rp->i_flag =| IWANT;
        sleep(rp, PPIPE);
    }
    rp->i_flag =| ILOCK;
}

/*
 * Unlock a pipe.
 * If WANT bit is on, wakeup.
 * This routine is also used to unlock inodes in general.
 */
prele(ip)
int *ip;
{
    register *rp;

    rp = ip;
    rp->i_flag =& ~ILOCK;
    if(rp->i_flag&IWANT) {
        rp->i_flag =& ~IWANT;
        wakeup(rp);
    }
}

ඒ ඇයි කියලා මට මුලින් තේරුම් ගන්න බැරි වුණා readp() ඇති නොකරයි prele(ip) ඇමතුමට පෙර wakeup(ip+1). පළමු දෙය නම් writep() එහි චක්රයේ ඇති හේතු, මෙය plock(ip), එය නම් අවහිර වීමට තුඩු දෙයි readp() මගේ අවහිරය තවම ඉවත් කර නැත, එබැවින් කෙසේ හෝ කේතය නිවැරදිව ක්‍රියා කළ යුතුය. බැලුවොත් wakeup(), එවිට එය අනාගතයේ දී ක්රියාත්මක කිරීමට සූදානම් ලෙස නිදාගැනීමේ ක්රියාවලිය පමණක් සලකුණු කරන බව පැහැදිලි වේ sched() ඇත්තටම එය දියත් කළා. ඒ නිසා readp() හේතු wakeup(), අගුල ඉවත් කරයි, සකසයි IREAD සහ ඇමතුම් sleep(ip+2)- මේ සියල්ල කලින් writep() චක්රය නැවත ආරම්භ කරයි.

මෙය හයවන සංස්කරණයේ වාහක විස්තරය සම්පූර්ණ කරයි. සරල කේතය, දුරදිග යන ප්රතිවිපාක.

Unix හි හත්වන සංස්කරණය (ජනවාරි 1979) බොහෝ නව යෙදුම් සහ කර්නල් විශේෂාංග හඳුන්වා දුන් නව ප්‍රධාන නිකුතුවකි (වසර හතරකට පසුව). ටයිප් වාත්තු කිරීම, වෘත්තීය සමිති සහ ව්‍යුහයන් වෙත ටයිප් කරන ලද පොයින්ටර් භාවිතය සම්බන්ධයෙන් ද එය සැලකිය යුතු වෙනස්කම් වලට භාජනය විය. කෙසේ වුවද වාහක කේතය ප්රායෝගිකව වෙනස් නොවේ. අපට මෙම සංස්කරණය මඟ හැරිය හැක.

Xv6, සරල යුනික්ස් වැනි කර්නලයකි

කර්නලය නිර්මාණය කිරීමට Xv6 Unix හි හයවන සංස්කරණය මගින් බලපෑමට ලක්ව ඇත, නමුත් එය x86 ප්‍රොසෙසර මත ක්‍රියාත්මක වීමට නවීන C වලින් ලියා ඇත. කේතය කියවීමට පහසු සහ තේරුම්ගත හැකි ය. තවද, TUHS සමඟ Unix මූලාශ්‍ර මෙන් නොව, ඔබට එය සම්පාදනය කිරීමට, එය වෙනස් කිරීමට සහ PDP 11/70 හැර වෙනත් දෙයක් මත ධාවනය කළ හැක. එබැවින්, මෙම කර්නලය විශ්ව විද්‍යාලවල මෙහෙයුම් පද්ධති පිළිබඳ අධ්‍යාපනික ද්‍රව්‍ය ලෙස බහුලව භාවිතා වේ. මූලාශ්ර Github මත ඇත.

කේතය පැහැදිලි සහ කල්පනාකාරී ක්රියාත්මක කිරීමක් අඩංගු වේ පයිප්ප.සී, තැටියේ ඉනෝඩයක් වෙනුවට මතකයේ බෆරයක් මගින් පිටුබලය ලැබේ. මෙහිදී මම සපයන්නේ "ව්‍යුහාත්මක නල මාර්ගය" සහ ශ්‍රිතයේ නිර්වචනය පමණි pipealloc():

#define PIPESIZE 512

struct pipe {
  struct spinlock lock;
  char data[PIPESIZE];
  uint nread;     // number of bytes read
  uint nwrite;    // number of bytes written
  int readopen;   // read fd is still open
  int writeopen;  // write fd is still open
};

int
pipealloc(struct file **f0, struct file **f1)
{
  struct pipe *p;

  p = 0;
  *f0 = *f1 = 0;
  if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
    goto bad;
  if((p = (struct pipe*)kalloc()) == 0)
    goto bad;
  p->readopen = 1;
  p->writeopen = 1;
  p->nwrite = 0;
  p->nread = 0;
  initlock(&p->lock, "pipe");
  (*f0)->type = FD_PIPE;
  (*f0)->readable = 1;
  (*f0)->writable = 0;
  (*f0)->pipe = p;
  (*f1)->type = FD_PIPE;
  (*f1)->readable = 0;
  (*f1)->writable = 1;
  (*f1)->pipe = p;
  return 0;

 bad:
  if(p)
    kfree((char*)p);
  if(*f0)
    fileclose(*f0);
  if(*f1)
    fileclose(*f1);
  return -1;
}

pipealloc() කාර්යයන් ඇතුළත් ඉතිරි ක්‍රියාත්මක කිරීමේ තත්වය සකසයි piperead(), pipewrite() и pipeclose(). සැබෑ පද්ධති ඇමතුම sys_pipe තුළ ක්රියාත්මක කරන ලද එතුමකි sysfile.c. ඔහුගේ සම්පූර්ණ කේතය කියවීමට මම නිර්දේශ කරමි. සංකීර්ණත්වය හයවන සංස්කරණයේ මූල කේතයේ මට්ටමේ පවතී, නමුත් එය කියවීමට වඩා පහසු සහ වඩාත් විනෝදජනක වේ.

Linux 0.01

Linux 0.01 මූලාශ්‍ර කේතය සොයා ගත හැක. ඔහුගේ නල මාර්ග ක්රියාත්මක කිරීම අධ්යයනය කිරීම සඳහා උපදෙස් දෙනු ඇත fs/pipe.c. මෙය නල මාර්ගය නියෝජනය කිරීම සඳහා ඉනෝඩයක් භාවිතා කරයි, නමුත් නල මාර්ගයම නවීන C වලින් ලියා ඇත. ඔබ 6 වන සංස්කරණ කේතය හරහා වැඩ කර ඇත්නම්, ඔබට මෙහි කරදරයක් නැත. කාර්යය පෙනෙන්නේ මෙයයි write_pipe():

int write_pipe(struct m_inode * inode, char * buf, int count)
{
    char * b=buf;

    wake_up(&inode->i_wait);
    if (inode->i_count != 2) { /* no readers */
        current->signal |= (1<<(SIGPIPE-1));
        return -1;
    }
    while (count-->0) {
        while (PIPE_FULL(*inode)) {
            wake_up(&inode->i_wait);
            if (inode->i_count != 2) {
                current->signal |= (1<<(SIGPIPE-1));
                return b-buf;
            }
            sleep_on(&inode->i_wait);
        }
        ((char *)inode->i_size)[PIPE_HEAD(*inode)] =
            get_fs_byte(b++);
        INC_PIPE( PIPE_HEAD(*inode) );
        wake_up(&inode->i_wait);
    }
    wake_up(&inode->i_wait);
    return b-buf;
}

ව්‍යුහයේ නිර්වචන දෙස නොබලා, ලිවීමේ ක්‍රියාවක ප්‍රතිඵලයක් වේද යන්න පරීක්ෂා කිරීමට ඉනෝඩ් යොමු ගණන භාවිතා කරන්නේ කෙසේදැයි ඔබට සොයා ගත හැක. SIGPIPE. byte-by-byte වැඩ කිරීමට අමතරව, මෙම කාර්යය ඉහත විස්තර කර ඇති අදහස් සමඟ සංසන්දනය කිරීම පහසුය. තර්කය පවා sleep_on/wake_up එතරම් පිටසක්වල බවක් නොපෙනේ.

නවීන ලිනක්ස් කර්නල්, FreeBSD, NetBSD, OpenBSD

මම ඉක්මනින් නවීන කර්නල් කිහිපයක් හරහා දිව ගියෙමි. ඔවුන් කිසිවකුට තවදුරටත් තැටි ක්‍රියාත්මක කිරීමක් නොමැත (පුදුමයක් නොවේ). ලිනක්ස් වලට තමන්ගේම ක්‍රියාත්මක කිරීමක් ඇත. නවීන BSD කර්නල් තුනේ ජෝන් ඩයිසන් විසින් ලියන ලද කේතය මත පදනම් වූ ක්‍රියාත්මක කිරීම් අඩංගු වුවද, වසර ගණනාවක් පුරා ඒවා එකිනෙකට වඩා වෙනස් වී ඇත.

කියවීමට fs/pipe.c (ලිනක්ස් මත) හෝ sys/kern/sys_pipe.c (*BSD මත), එය සැබෑ කැපවීමක් අවශ්ය වේ. අද කේතය කාර්ය සාධනය සහ දෛශික සහ අසමමුහුර්ත I/O වැනි විශේෂාංග සඳහා සහාය වේ. මතකය වෙන් කිරීම, අගුලු දැමීම සහ කර්නල් වින්‍යාසය පිළිබඳ විස්තර බොහෝ සෙයින් වෙනස් වේ. හඳුන්වාදීමේ මෙහෙයුම් පද්ධති පාඨමාලාවක් සඳහා විද්‍යාලවලට අවශ්‍ය වන්නේ මෙය නොවේ.

කෙසේ වෙතත්, මම පැරණි රටා (ජනනය කිරීම වැනි) හාරා ගැනීමට උනන්දු විය SIGPIPE සහ ආපසු EPIPE සංවෘත නල මාර්ගයකට ලියන විට) මෙම විවිධ නවීන කර්නල් වල. මම සැබෑ ජීවිතයේදී කවදාවත් PDP-11 පරිගණකයක් නොදකිනු ඇත, නමුත් මා ඉපදීමට වසර ගණනාවකට පෙර ලියා ඇති කේතයෙන් ඉගෙන ගැනීමට බොහෝ දේ ඇත.

2011 දී දිවි කපූර් විසින් ලියන ලද ලිපියක්:පයිප්ප සහ FIFO වල Linux Kernel ක්‍රියාත්මක කිරීම" ලිනක්ස් හි නල මාර්ග (තවමත්) ක්‍රියා කරන ආකාරය පිළිබඳ දළ විශ්ලේෂණයක් සපයයි. ඒ ලිනක්ස් හි මෑතකාලීන කැපවීම අන්තර්ක්‍රියා වල නල මාර්ග ආකෘතියක් නිරූපණය කරයි, එහි හැකියාවන් තාවකාලික ගොනු වලට වඩා වැඩි ය; සහ හයවන සංස්කරණය Unix කර්නලයේ "ඉතා ගතානුගතික අගුලු දැමීමෙන්" නල මාර්ග කෙතරම් දුරට පැමිණ තිබේද යන්න පෙන්වයි.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න