සටහන: පිළිතුර මෙම වෙබ් අඩවියේ සහ යුනික්ස්.ස්ටැක්එක්ස්චේන්ජ්.කොම් හි සම වයසේ මිතුරන් විසින් පර්යේෂණ හා කියවීම් පිළිබඳව රැස්කර ගෙන ඇති මෙම යාන්ත්රණයන් පිළිබඳ මගේම අවබෝධය පිළිබිඹු කරයි, කාලයත් සමඟ යාවත්කාලීන වේ. ප්රශ්න ඇසීමට පසුබට නොවන්න. විධාන සමඟ ෂෙල් තුළ සිස්කල් ක්රියා කරන්නේ කෙසේදැයි බැලීමට උත්සාහ කරන ලෙස මම ඔබට යෝජනා කරමි strace
. කරුණාකර අභ්යන්තර හෝ සිස්කල් යන සංකල්පයෙන් බිය නොවන්න - ෂෙල් දේවල් කරන්නේ කෙසේද යන්න තේරුම් ගැනීම සඳහා ඔබට ඒවා දැන ගැනීමට හෝ භාවිතා කිරීමට අවශ්ය නැත, නමුත් ඒවා අනිවාර්යයෙන්ම තේරුම් ගැනීමට උපකාරී වේ.
ටීඑල්; ඩී.ආර්
|
පයිප්ප තැටියේ ඇතුළත් කිරීමක් සමඟ සම්බන්ධ නොවේ, එබැවින් තැටි ගොනු පද්ධතියේ ඉනෝඩ අංකයක් නොමැත (නමුත් කර්නල්-අවකාශයේ පයිප්ෆ් අතථ්ය ගොනු පද්ධතියේ ඉනෝඩ ඇත ), නමුත් යළි-යොමුවීම් බොහෝ විට ලිපිගොනු ඇතුළත් වන අතර ඒවාට තැටි ඇතුළත් කිරීම් ඇති අතර එම නිසා අනුරූප වේ ඉනෝඩය.
- පයිප්පවලට
lseek()
නොහැකි බැවින් විධාන වලට සමහර දත්ත කියවා නැවත පෙරළා දැමිය නොහැක, නමුත් ඔබ එය හරවා යවන විට >
හෝ <
සාමාන්යයෙන් එය ගොනුවක් විය lseek()
හැකි බැවින් විධාන වලට කැමති පරිදි සැරිසැරීමට හැකිය.
- යළි-යොමුවීම් යනු ගොනු විස්තර කරන්නන් මත සිදුකරන උපාමාරු ය, ඒවා බොහෝ විය හැකිය; පයිප්ප සතුව ඇත්තේ ගොනු විස්තර දෙකක් පමණි - එකක් වම් විධානය සඳහා සහ එකක් දකුණු විධානය සඳහා ය
- සම්මත ධාරා සහ පයිප්ප නැවත හරවා යැවීම දෙකම ආරක්ෂිත වේ.
- පයිප්ප සෑම විටම පාහේ දෙබලක සම්බන්ධ වන අතර එම නිසා ක්රියාවලි යුගල සම්බන්ධ වේ; යළි-යොමුවීම් - සෑම විටම නොවේ, මෙම අවස්ථා දෙකෙහිම ප්රති ing ලයක් ලෙස ගොනු විස්තර කරන්නන් උප ක්රියාවලි මගින් උරුම වේ.
- පයිප්ප සැමවිටම ගොනු විස්තර කරන්නන් (යුගලයක්) සම්බන්ධ කරයි, යළි-යොමුවීම් - එක්කෝ මාර්ග නාමයක් හෝ ගොනු විස්තරයක් භාවිතා කරන්න.
- පයිප්ප අන්තර් ක්රියාදාම සන්නිවේදන ක්රමයක් වන අතර, යළි-යොමුවීම් යනු විවෘත ලිපිගොනු හෝ ගොනු වැනි වස්තූන් හසුරුවීම පමණි
dup2()
සත්ය දත්ත ප්රවාහයක් සිදුවන ලිපිගොනු විස්තර කරුවන්ගේ පිටපත් සැපයීම සඳහා දෙදෙනාම කබායට යටින් සිස්කල් භාවිතා කරති .
- යළි-යොමුවීම් "ගෝලීයව"
exec
බිල්ට් විධාන සමඟ යෙදිය හැකිය ( මෙය සහ මෙය බලන්න ), එබැවින් ඔබ කරන්නේ නම් exec > output.txt
සෑම විධානයක්ම output.txt
එතැන් සිට ලියනු ඇත. |
පයිප්ප යොදවන්නේ වත්මන් විධානය සඳහා පමණි (එයින් අදහස් කරන්නේ සරල විධානයක් හෝ උප-ෂෙල් වැනි seq 5 | (head -n1; head -n2)
හෝ සංයුක්ත විධාන සඳහා ය.
- ලිපිගොනු නැවත හරවා යැවීම සිදු කළ විට, වැනි දේ
echo "TEST" > file
සහ echo "TEST" >> file
දෙකම open()
එම ගොනුවේ syscall භාවිතා කරයි ( මෙයද බලන්න ) සහ එය ලබා දීමට ගොනු විස්තරයක් ලබා ගන්න dup2()
. පයිප්ප |
පමණක් භාවිතා pipe()
සහ dup2()
syscall.
- යළි-යොමුවීම් වලට ගොනු සහ නාමාවලි අවසර ඇතුළත් වේ; නිර්නාමික පයිප්පවල සාමාන්යයෙන් අවසරයන් ඇතුළත් නොවේ (එනම් ඔබට පයිප්පයක් සෑදිය හැකිද නැද්ද යන්න), නමුත් නම් කරන ලද පයිප්ප (සාදන ලද
mkfifo
) සාමාන්ය ගොනු අවසරයන් සහ කියවීම්-ලිවීම්-ක්රියාත්මක කිරීමේ බිටු ඇතුළත් වේ.
- විධාන ක්රියාත්මක වන තාක් දුරට, පයිප්ප සහ යළි හරවා යැවීම ගොනු විස්තර කරන්නන්ට වඩා වැඩි නොවේ - ලිපිගොනු වැනි වස්තූන්, ඒවා අන්ධ ලෙස ලිවීමට හෝ අභ්යන්තරව හැසිරවීමට (ඒවා අනපේක්ෂිත හැසිරීම් ඇති කළ හැකිය;
apt
නිදසුනක් ලෙස, stdout වෙත ලිවීමට පවා නැඹුරු වේ. නැවත හරවා යැවීමක් ඇති බව එය දන්නේ නම්).
හැදින්වීම
මෙම යාන්ත්රණ දෙක එකිනෙකට වෙනස් වන්නේ කෙසේද යන්න තේරුම් ගැනීම සඳහා, ඒවායේ අත්යවශ්ය ගුණාංග, දෙක පිටුපස ඇති ඉතිහාසය සහ සී ක්රමලේඛන භාෂාවෙන් ඒවායේ මූලයන් තේරුම් ගැනීම අවශ්ය වේ. ඇත්ත වශයෙන්ම, ගොනු විස්තර කරන්නන් යනු කුමක්ද dup2()
සහ pipe()
පද්ධති ඇමතුම් ක්රියා කරන්නේ කෙසේද සහ කෙසේද යන්න දැන ගැනීම අත්යවශ්ය වේ lseek()
. ෂෙල් යනු මෙම යාන්ත්රණයන් පරිශීලකයාට වියුක්ත කිරීමේ ක්රමයක් ලෙස අදහස් කරන නමුත් වියුක්තයට වඩා ගැඹුරට හෑරීම ෂෙල්ගේ හැසිරීමේ සැබෑ ස්වභාවය තේරුම් ගැනීමට උපකාරී වේ.
යළි-යොමුවීම් සහ පයිප්පවල මූලාරම්භය
ඩෙනිස් Ritche ලිපිය අනුව අනාවැකි ඉතිහාසය තුල මතභේද , පයිප්ප වලින් සම්භවය 1964 අභ්යන්තර සටහනක් විසින් මැල්කම් ඩග්ලස් ලහිරුගේ , ඔවුන් කටයුතු කරමින් සිටින අවස්ථාවක Multics පද්දතිය මෙහෙයුම් පද්ධතිය . උපුටා ගැනීම:
මගේ ශක්තිමත්ම කරුණු කෙටියෙන් කිවහොත්:
- උද්යාන හෝස් වැනි වැඩසටහන් සම්බන්ධ කිරීමට අපට ක්රම කිහිපයක් තිබිය යුතුය - වෙනත් ආකාරයකින් දත්ත සම්බාහනය කිරීමට අවශ්ය වූ විට තවත් කොටසකට ඉස්කුරුප්පු කරන්න. IO හි මාර්ගය ද මෙයයි.
පෙනෙන දෙය නම්, එකල වැඩසටහන් තැටියට ලිවීමේ හැකියාව තිබූ නමුත් ප්රතිදානය විශාල නම් එය අකාර්යක්ෂම වීමයි. යුනික්ස් පයිප්ලයින් වීඩියෝවෙන් බ්රයන් කර්නිගන් ගේ පැහැදිලි කිරීම උපුටා දැක්වීමට :
පළමුවෙන්ම, ඔබට එක් විශාල දැවැන්ත වැඩසටහනක් ලිවීමට අවශ්ය නැත - ඔබ සතුව දැනටමත් පවතින කුඩා වැඩසටහන් තිබේ, ඒවා දැනටමත් කාර්යයේ කොටස් කළ හැකිය ... තවත් දෙයක් නම්, ඔබ ප්රොසෙස් කරන දත්ත ප්රමාණය නොගැලපේ නම් ඔබ එය ගොනුවක ගබඩා කර ඇත ... මන්ද මතක තබා ගන්න, මේ දේවල් පිළිබඳ තැටි තිබූ දිනවල, අපි වාසනාවන්ත නම්, මෙගාබයිට් එකක් හෝ දත්ත දෙකක් තිබුනි ... එබැවින් නල මාර්ගයට කිසි විටෙකත් සම්පූර්ණ ප්රතිදානය ක්ෂණිකව කිරීමට සිදු නොවීය. .
මේ අනුව සංකල්පීය වෙනස පැහැදිලිව පෙනේ: පයිප්ප යනු වැඩසටහන් එකිනෙකා සමඟ කතා කිරීමේ යාන්ත්රණයකි. යළි-යොමුවීම් - මූලික මට්ටමින් ගොනු කිරීමට ලිවීමේ ක්රමයකි. අවස්ථා දෙකේදීම, ෂෙල් විසින් මේ කාරණා දෙක පහසු කරයි, නමුත් කබායට යටින්, සිදුවෙමින් පවතින බොහෝ දේ ඇත.
ගැඹුරට යාම: සිස්කල් සහ කවචයේ අභ්යන්තර කටයුතු
අපි ආරම්භ කරන්නේ ගොනු විස්තර කරන්නා යන සංකල්පයෙන් . ගොනු විස්තර කරන්නන් මූලික වශයෙන් විස්තර කරන්නේ විවෘත ගොනුවක් (එය තැටියේ හෝ මතකයේ හෝ නිර්නාමික ගොනුවක් වේවා), එය පූර්ණ සංඛ්යාවක් මගින් නිරූපණය කෙරේ. සම්මත දත්ත ප්රවාහයන් දෙක (stdin, stdout, stderr) පිළිවෙලින් ගොනු විස්තර කරන්නන් 0,1 සහ 2 වේ. ඔවුන් කොහේ ඉඳන්ද ? හොඳයි, ෂෙල් විධාන වලදී ගොනු විස්තර කරන්නන් ඔවුන්ගේ මව් - ෂෙල් වෙතින් උරුම වේ. සෑම ක්රියාවලියක් සඳහාම එය පොදුවේ සත්යයකි - ළමා ක්රියාවලිය දෙමව්පියන්ගේ ලිපිගොනු විස්තර කරන්නන්ට උරුම වේ. ඩීමන් සඳහා, උරුම වී ඇති සියලුම ගොනු විස්තර වසා දැමීම සහ / හෝ වෙනත් ස්ථාන වෙත හරවා යැවීම සාමාන්ය දෙයකි.
නැවත හරවා යැවීම වෙත. ඇත්තටම එය කුමක්ද? එය විධානය සඳහා ගොනු විස්තර සකස් කිරීමට ෂෙල්ට පවසන යාන්ත්රණයකි (මක්නිසාද යත් විධානය ක්රියාත්මක වීමට පෙර නැවත හරවා යැවීම ෂෙල් මඟින් සිදු කරන බැවිනි), සහ පරිශීලකයා යෝජනා කළ ස්ථානයට ඒවා යොමු කරන්න. මෙම සම්මත අර්ථ දැක්වීම ප්රතිදානය හරවා යැවීමේ වනුයේ
[n]>word
ඒ [n]
ගොනුව descriptor අංකය නැත. ඔබ කරන echo "Something" > /dev/null
විට අංක 1 එහි ගම්ය වේ, සහ echo 2> /dev/null
.
dup2()
පද්ධති ඇමතුම හරහා ගොනු විස්තරය අනුපිටපත් කිරීමෙන් මෙය සිදු කෙරේ . අපි ගනිමු df > /dev/null
. කවචය ක්රියාත්මක වන ළමා ක්රියාවලියක් නිර්මාණය කරනු ඇත df
, නමුත් ඊට පෙර එය ගොනු විස්තර කරන්නා /dev/null
# 3 ලෙස විවෘත වන අතර dup2(3,1)
එය නිකුත් කරනු ඇත, එමඟින් ගොනු විස්තර 3 හි පිටපතක් සාදනු ඇති අතර එහි පිටපත 1 වනු ඇත. ඔබට ලිපිගොනු දෙකක් ඇති ආකාරය file1.txt
සහ file2.txt
, සහ ඔබ කරන විට ඔබට cp file1.txt file2.txt
එකම ලිපිගොනු දෙකක් ඇත, නමුත් ඔබට ඒවා ස්වාධීනව හැසිරවිය හැකිද? ඒකත් මෙතනමයි. ධාවනය වීමට පෙර, පසුව bash
එය යථා dup(1,10)
තත්වයට පත් කිරීම සඳහා පිටපත් ගොනු විස්තරයක් # 1 stdout
(සහ එම පිටපත fd # 10 වනු ඇත) කිරීමට බොහෝ විට ඔබට දැක ගත හැකිය . වැදගත් වන්නේ ඔබ විසින් සාදන ලද විධාන සලකා බලන විටය(ඒවා කවචයේම කොටසක් වන අතර කිසිදු ගොනුවක් /bin
හෝ වෙනත් තැනක නොමැත) හෝ අන්තර්ක්රියාකාරී නොවන කවචයේ සරල විධානයන් , කවචය ළමා ක්රියාවලියක් නිර්මාණය නොකරයි.
ඉන් පසුව අපි වැනි දේවල් ඇති [n]>&[m]
හා [n]&<[m]
. මෙය ගොනු විස්තර කරුවන් අනුපිටපත් කිරීමකි, එය dup2()
දැන් පවතින යාන්ත්රණයම ෂෙල් සින්ටැක්ස් තුළ ඇති අතර එය පරිශීලකයාට පහසුවෙන් ලබා ගත හැකිය.
නැවත හරවා යැවීම පිළිබඳව සැලකිල්ලට ගත යුතු වැදගත් කරුණක් නම් ඒවායේ ඇණවුම සවි කර නොමැති නමුත් පරිශීලකයාට අවශ්ය දේ ෂෙල් විසින් අර්ථ නිරූපණය කරන්නේ කෙසේද යන්න වැදගත් වේ. පහත සඳහන් දෑ සසඳා බලන්න:
# Make copy of where fd 2 points , then redirect fd 2
$ ls -l /proc/self/fd/ 3>&2 2> /dev/null
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
lrwx------ 1 runner user 64 Sep 13 00:08 3 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/29/fd
# redirect fd #2 first, then clone it
$ ls -l /proc/self/fd/ 2> /dev/null 3>&2
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
l-wx------ 1 user user 64 Sep 13 00:08 3 -> /dev/null
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/31/fd
ෂෙල් ස්ක්රිප්ටින්හි මේවා ප්රායෝගිකව භාවිතා කිරීම බහුකාර්ය විය හැකිය:
සහ තවත් බොහෝ දේ.
සමග, ජලනල කාර්මික ශිල්පය pipe()
සහdup2()
ඉතින් පයිප්ප නිර්මාණය කරන්නේ කෙසේද? හරහා pipe()
syscall , ආදාන ලෙස නම් (ලැයිස්තුව හෙවත්) රැසක් ගෙන ඇත pipefd
වර්ගයේ භාණ්ඩ දෙකක් int
(පූර්ණ සංඛ්යාවක්). එම නිඛිල දෙක ගොනු විස්තර කරන්නන් වේ. මෙම pipefd[0]
නල යන කියවා අවසන් වනු ඇති අතර, pipefd[1]
ලිවීම් අවසන් වනු ඇත. ඒ නිසා දී df | grep 'foo'
, grep
පිටපතක් ලබා ඇත pipefd[0]
හා df
පිටපතක් ලබා ඇත pipefd[1]
. නමුත් කෙසේද? ඇත්ත වශයෙන්ම, dup2()
සිස්කල්ගේ මැජික් සමඟ . සඳහා df
අපගේ නිදසුනේ, එහෙනම් අපි කිව්වොත් pipefd[1]
ෂෙල්, ළමා කළ නිසා ඇත කරන්නේ, # 4 ඇත dup2(4,1)
(මගේ මතක cp
උදාහරණයක්?), පසුව කරන්නේ execve()
ඇත්තටම ක්රියාත්මක කිරීමට df
. ස්වාභාවිකවම,df
ගොනු විස්තර කරන්නා # 1 උරුම කර ගනු ඇත, නමුත් එය තවදුරටත් පර්යන්තයට යොමු නොවන බව නොදැන සිටියි, නමුත් ඇත්ත වශයෙන්ම fd # 4, එය ඇත්ත වශයෙන්ම පයිප්පයේ ලිවීමේ අවසානය වේ. ස්වාභාවිකවම, grep 'foo'
විවිධ ගොනු විස්තර කිරීම් හැරුණු විට එකම දේ සිදුවනු ඇත .
දැන්, සිත්ගන්නාසුලු ප්රශ්නය: fd # 1 පමණක් නොව fd # 2 යළි හරවා යවන පයිප්ප සෑදිය හැකිද? ඔව්, ඇත්ත වශයෙන්ම එයයි |&
. POSIX ප්රමිතියට df 2>&1 | grep 'foo'
එම අරමුණු සඳහා සින්ටැක්ස් සඳහා සහය දැක්වීමට ෂෙල් විධාන භාෂාව අවශ්ය වන නමුත් bash
එය |&
එසේම වේ.
සැලකිල්ලට ගත යුතු වැදගත්ම දෙය නම් පයිප්ප සෑම විටම ගොනු විස්තර කරන්නන් සමඟ කටයුතු කිරීමයි. තැටියේ ගොනු නාමයක් ඇති නළයක් තිබේ FIFO
හෝ නම් කර ඇති අතර ඔබ එය ගොනුවක් ලෙස භාවිතා කරමු, නමුත් පයිප්පයක් මෙන් හැසිරේ. නමුත් |
පයිප්ප වර්ග යනු නිර්නාමික පයිප්ප ලෙස හැඳින්වේ - ඒවාට ගොනු නාමයක් නොමැත, මන්ද ඒවා සැබවින්ම එකට සම්බන්ධ වී ඇති වස්තු දෙකක් පමණි. අප ලිපිගොනු සමඟ ගනුදෙනු නොකිරීමද වැදගත් ඇඟවීමක් කරයි: පයිප්පවලට lseek()
නොහැකි ය. ලිපිගොනු, මතකයේ හෝ තැටියේ ස්ථිතික වේ - වැඩසටහන් වලට lseek()
සිස්කාල් භාවිතා කර බයිට් 120 වෙත පනින්න, පසුව බයිට් 10 වෙත ආපසු යන්න, ඉන්පසු අවසානය දක්වා ඉදිරියට යන්න. පයිප්ප ස්ථිතික නොවේ - ඒවා අනුක්රමික වන අතර එම නිසා ඔබට ඒවායින් ලැබෙන දත්ත නැවත පෙරළා දැමිය නොහැකlseek()
. සමහර වැඩසටහන් ගොනුවෙන් හෝ පයිප්පයෙන් කියවන්නේ නම් මෙය දැනුවත් කරයි, එබැවින් කාර්යක්ෂම කාර්ය සාධනය සඳහා අවශ්ය වෙනස්කම් කළ හැකිය; වෙනත් වචන වලින් කිවහොත්, prog
මා එසේ කරන්නේ නම් cat file.txt | prog
හෝ හඳුනාගත හැකිය prog < input.txt
. ඒ සඳහා සැබෑ වැඩ උදාහරණය වලිගයයි .
පයිප්පවල ඇති අනෙක් ඉතා සිත්ගන්නාසුලු දේපල දෙක නම්, ඔවුන් සතුව බෆරයක් ඇති අතර එය ලිනක්ස් හි බයිට් 4096 ක් වන අතර ඇත්ත වශයෙන්ම ඒවා ලිනක්ස් ප්රභව කේතයේ අර්ථ දක්වා ඇති පරිදි ගොනු පද්ධතියක් ඇත ! ඒවා හුදෙක් දත්ත සම්ප්රේෂණය කිරීමේ වස්තුවක් නොවේ, ඒවා දත්ත ව්යුහයකි! ඇත්ත වසයෙන් ම, පවතී ජලනල හා FIFOs දෙකම කළමනාකරණය කරනු ලබන pipefs ගොනු පද්ධතිය, නිසා, පයිප්ප සඳහා inode ඇති අදාළ ගොනු පද්ධතිය මත අංකය:
# Stdout of ls is wired to pipe
$ ls -l /proc/self/fd/ | cat
lrwx------ 1 user user 64 Sep 13 00:02 0 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:02 1 -> pipe:[15655630]
lrwx------ 1 user user 64 Sep 13 00:02 2 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:02 3 -> /proc/22/fd
# stdin of ls is wired to pipe
$ true | ls -l /proc/self/fd/0
lr-x------ 1 user user 64 Sep 13 03:58 /proc/self/fd/0 -> 'pipe:[54741]'
ලිනක්ස් පයිප්ප හරවා යැවීම මෙන් ඒක දිශානුගත වේ. සමහර යුනික්ස් වැනි ක්රියාත්මක කිරීම් වලදී - ද්වි-දිශානුගත පයිප්ප ඇත. ෂෙල් ස්ක්රිප්ටින් මැජික් සමඟ වුවද, ඔබට ලිනක්ස් මත ද්වි-දිශානුගත පයිප්ප සෑදිය හැකිය .
මෙයද බලන්න:
thing1 > temp_file && thing2 < temp_file
පයිප්ප සමඟ වඩාත් පහසු කිරීමට ඔබ සඳහන් කළා. නමුත් මෙය සිදු කිරීම සඳහා>
ක්රියාකරු නැවත භාවිතා නොකරන්නේ ඇයි , උදා:thing1 > thing2
විධාන සඳහාthing1
සහthing2
? අතිරේක ක්රියාකරුවෙකු වන්නේ ඇයි|
?