எடுத்துக்காட்டுகளுடன் லினக்ஸில் கோப்பு விளக்கம்

ஒருமுறை, ஒரு நேர்காணலின் போது, ​​என்னிடம் கேட்கப்பட்டது, வட்டில் இடம் இல்லாமல் போனதால் சேவை வேலை செய்யவில்லை என்றால் நீங்கள் என்ன செய்வீர்கள்?

நிச்சயமாக, இந்த இடம் என்ன ஆக்கிரமித்துள்ளது என்பதை நான் பார்க்கிறேன், முடிந்தால், அந்த இடத்தை சுத்தம் செய்வேன் என்று பதிலளித்தேன்.
பின்னர் நேர்காணல் செய்பவர் கேட்டார், பகிர்வில் இலவச இடம் இல்லையென்றால் என்ன செய்வது, ஆனால் எல்லா இடத்தையும் எடுக்கும் எந்த கோப்புகளையும் நீங்கள் காணவில்லையா?

இதற்கு நான் சொன்னேன், நீங்கள் எப்போதும் திறந்த கோப்பு விளக்கங்களைப் பார்க்கலாம், எடுத்துக்காட்டாக lsof கட்டளையைப் பயன்படுத்தி, எந்த பயன்பாடு கிடைக்கக்கூடிய அனைத்து இடத்தையும் எடுத்துக் கொண்டுள்ளது என்பதைப் புரிந்து கொள்ளுங்கள், பின்னர் தரவு தேவையா என்பதைப் பொறுத்து சூழ்நிலைகளுக்கு ஏற்ப செயல்படலாம். .

நேர்காணல் செய்பவர் என்னிடம் கடைசி வார்த்தையில் குறுக்கிட்டு, அவரது கேள்வியைச் சேர்த்தார்: "எங்களுக்கு தரவு தேவையில்லை என்று வைத்துக்கொள்வோம், இது ஒரு பிழைத்திருத்த பதிவு மட்டுமே, ஆனால் பிழைத்திருத்தத்தை எழுத முடியாததால் பயன்பாடு வேலை செய்யாது"?

"சரி," நான் பதிலளித்தேன், "பயன்பாட்டு கட்டமைப்பில் பிழைத்திருத்தத்தை அணைத்து அதை மறுதொடக்கம் செய்யலாம்."
நேர்காணல் செய்பவர் எதிர்த்தார்: "இல்லை, எங்களால் பயன்பாட்டை மறுதொடக்கம் செய்ய முடியாது, எங்களிடம் முக்கியமான தரவு இன்னும் நினைவகத்தில் சேமிக்கப்பட்டுள்ளது, மேலும் முக்கியமான வாடிக்கையாளர்கள் சேவையுடன் இணைக்கப்பட்டுள்ளனர், அதை மீண்டும் இணைக்க நாங்கள் கட்டாயப்படுத்த முடியாது."

"சரி," நான் சொன்னேன், "எங்களால் பயன்பாட்டை மறுதொடக்கம் செய்ய முடியாவிட்டால், தரவு நமக்கு முக்கியமில்லை என்றால், இந்த திறந்த கோப்பை ls கட்டளையில் காணாவிட்டாலும், கோப்பு விளக்கத்தின் மூலம் வெறுமனே அழிக்கலாம். கோப்பு முறைமையில்."

நேர்காணல் செய்பவர் மகிழ்ச்சியடைந்தார், ஆனால் நான் இல்லை.

பிறகு நான் நினைத்தேன், என் அறிவைச் சோதிக்கும் நபர் ஏன் ஆழமாகத் தோண்டுவதில்லை? ஆனால் தரவு முக்கியமானது என்றால் என்ன செய்வது? ஒரு செயல்முறையை மறுதொடக்கம் செய்ய முடியாவிட்டால், அந்த செயல்முறையானது கோப்பு முறைமையில் இலவச இடம் இல்லாத பகிர்வில் எழுதப்பட்டால் என்ன செய்வது? ஏற்கனவே எழுதப்பட்ட தரவுகளை மட்டுமல்ல, இந்த செயல்முறை எழுதும் அல்லது எழுத முயற்சிக்கும் தரவையும் இழக்க முடியாவிட்டால் என்ன செய்வது?

துசிக்

எனது தொழில் வாழ்க்கையின் ஆரம்பத்தில், பயனர் தகவல்களைச் சேமிக்கத் தேவையான ஒரு சிறிய பயன்பாட்டை உருவாக்க முயற்சித்தேன். பின்னர் நான் நினைத்தேன், பயனரை அவருடைய தரவுகளுடன் எவ்வாறு பொருத்துவது. உதாரணமாக, என்னிடம் இவானோவ் இவான் இவனோவிச் இருக்கிறார், அவரிடம் சில தகவல்கள் உள்ளன, ஆனால் அவர்களுடன் நான் எப்படி நட்பு கொள்வது? "துசிக்" என்ற நாய் இந்த இவனுக்கே சொந்தமானது என்பதை என்னால் நேரடியாக சுட்டிக்காட்ட முடியும். ஆனால் அவர் தனது பெயரை மாற்றி, இவானுக்குப் பதிலாக, எடுத்துக்காட்டாக, ஒல்யாவாக மாறினால் என்ன செய்வது? எங்கள் ஒலியா இவனோவ்னா இவனோவாவுக்கு இனி ஒரு நாய் இருக்காது, எங்கள் துசிக் இன்னும் இல்லாத இவானுக்கு சொந்தமானது என்று மாறிவிடும். ஒவ்வொரு பயனருக்கும் ஒரு தனிப்பட்ட அடையாளங்காட்டியை (ஐடி) வழங்கிய தரவுத்தளமானது இந்தச் சிக்கலைத் தீர்க்க உதவியது, மேலும் எனது துசிக் இந்த ஐடியுடன் இணைக்கப்பட்டது, இது உண்மையில் ஒரு வரிசை எண்ணாகும். இதனால், சீட்டின் உரிமையாளருக்கு ஐடி எண் 2 இருந்தது, சில சமயங்களில் இவான் இந்த ஐடியின் கீழ் இருந்தார், பின்னர் ஒல்யா அதே ஐடியின் கீழ் ஆனார். மனிதநேயம் மற்றும் கால்நடை வளர்ப்பின் பிரச்சினை நடைமுறையில் தீர்க்கப்பட்டது.

கோப்பு விளக்கம்

இந்த பைலுடன் வேலை செய்யும் பைல் மற்றும் புரோகிராம் பிரச்சனை நமது நாய்க்கும் மனிதனுக்கும் ஏறக்குறைய ஒரே மாதிரியாக உள்ளது. நான் ivan.txt என்ற கோப்பைத் திறந்து அதில் துசிக் என்ற வார்த்தையை எழுதத் தொடங்கினேன், ஆனால் கோப்பில் முதல் எழுத்தான “t” ஐ மட்டுமே எழுத முடிந்தது, மேலும் இந்த கோப்பு யாரோ ஒருவரால் மறுபெயரிடப்பட்டது, எடுத்துக்காட்டாக, olya.txt. ஆனால் கோப்பு அப்படியே உள்ளது, இன்னும் எனது சீட்டை அதில் பதிவு செய்ய விரும்புகிறேன். ஒவ்வொரு முறையும் சிஸ்டம் கால் மூலம் கோப்பு திறக்கப்படும் திறந்த எந்த நிரலாக்க மொழியிலும் நான் ஒரு தனிப்பட்ட ஐடியைப் பெறுகிறேன், அது என்னை ஒரு கோப்பில் சுட்டிக்காட்டுகிறது, இந்த ஐடி கோப்பு விளக்கமாகும். இந்தக் கோப்பை அடுத்து யார் என்ன செய்கிறார்கள் என்பது முக்கியமல்ல, அதை நீக்கலாம், மறுபெயரிடலாம், உரிமையாளரை மாற்றலாம் அல்லது படிக்கவும் எழுதவும் உரிமைகள் பறிக்கப்படலாம், இன்னும் எனக்கு அணுகல் இருக்கும். அதற்கு, ஏனென்றால் கோப்பைத் திறக்கும் நேரத்தில், அதைப் படிக்க மற்றும்/அல்லது எழுத எனக்கு உரிமைகள் இருந்தன, மேலும் நான் அதனுடன் வேலை செய்யத் தொடங்கினேன், அதாவது நான் அதைத் தொடர்ந்து செய்ய வேண்டும்.

Linux இல், libc நூலகம் இயங்கும் ஒவ்வொரு பயன்பாட்டிற்கும் (செயல்முறை) 3 என்ற எண்ணில் 0,1,2 விளக்கக் கோப்புகளைத் திறக்கிறது. கூடுதல் தகவல்களை இணைப்புகளில் காணலாம் மனிதன் stdio и மனிதன் stdout

  • கோப்பு விளக்கம் 0 STDIN என அழைக்கப்படுகிறது மற்றும் பயன்பாட்டு உள்ளீட்டுடன் தொடர்புடையது
  • கோப்பு விளக்கம் 1 STDOUT என்று அழைக்கப்படுகிறது மற்றும் அச்சு கட்டளைகள் போன்ற தரவை வெளியிட பயன்பாடுகளால் பயன்படுத்தப்படுகிறது.
  • கோப்பு விளக்கம் 2 STDERR என அழைக்கப்படுகிறது மற்றும் பிழை செய்திகளை வெளியிட பயன்பாடுகளால் பயன்படுத்தப்படுகிறது.

உங்கள் நிரலில் நீங்கள் படிக்க அல்லது எழுதுவதற்கு ஏதேனும் கோப்பைத் திறந்தால், பெரும்பாலும் நீங்கள் முதல் இலவச ஐடியைப் பெறுவீர்கள், அது எண் 3 ஆக இருக்கும்.

கோப்பு விவரிப்பாளர்களின் பட்டியலை அதன் PID தெரிந்தால், எந்தவொரு செயல்முறைக்கும் பார்க்க முடியும்.

எடுத்துக்காட்டாக, பாஷ் கன்சோலைத் திறந்து, எங்கள் செயல்முறையின் PID ஐப் பார்ப்போம்

[user@localhost ]$ echo $$
15771

இரண்டாவது கன்சோலில் இயக்கலாம்

[user@localhost ]$ ls -lah /proc/15771/fd/
total 0
dr-x------ 2 user user  0 Oct  7 15:42 .
dr-xr-xr-x 9 user user  0 Oct  7 15:42 ..
lrwx------ 1 user user 64 Oct  7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 255 -> /dev/pts/21

இந்தக் கட்டுரையின் நோக்கங்களுக்காக நீங்கள் கோப்பு விளக்க எண் 255 ஐப் பாதுகாப்பாகப் புறக்கணிக்கலாம்; இது அதன் தேவைகளுக்காக பாஷ் மூலம் திறக்கப்பட்டது, இணைக்கப்பட்ட நூலகத்தால் அல்ல.

இப்போது அனைத்து 3 விளக்கக் கோப்புகளும் போலி டெர்மினல் சாதனத்துடன் இணைக்கப்பட்டுள்ளன /dev/pts, ஆனால் நாம் இன்னும் அவற்றைக் கையாளலாம், எடுத்துக்காட்டாக, அவற்றை இரண்டாவது கன்சோலில் இயக்கலாம்

[user@localhost ]$ echo "hello world" > /proc/15771/fd/0

மற்றும் முதல் கன்சோலில் பார்ப்போம்

[user@localhost ]$ hello world

வழிமாற்று மற்றும் குழாய்

இந்த 3 விளக்கக் கோப்புகளை பாஷ் உட்பட எந்தச் செயலிலும் எளிதாக மேலெழுதலாம், உதாரணமாக இரண்டு செயல்முறைகளை இணைக்கும் குழாய் மூலம், பார்க்கவும்

[user@localhost ]$ cat /dev/zero | sleep 10000

இந்த கட்டளையை நீங்களே இயக்கலாம் ஸ்ட்ரேஸ் -எஃப் உள்ளே என்ன நடக்கிறது என்று பாருங்கள், ஆனால் நான் உங்களுக்கு சுருக்கமாக சொல்கிறேன்.

PID 15771 உடன் எங்கள் பெற்றோர் பாஷ் செயல்முறை எங்கள் கட்டளையை பாகுபடுத்தி, எத்தனை கட்டளைகளை இயக்க விரும்புகிறோம் என்பதைப் புரிந்துகொள்கிறோம், எங்கள் விஷயத்தில் அவற்றில் இரண்டு உள்ளன: பூனை மற்றும் தூக்கம். இரண்டு குழந்தை செயல்முறைகளை உருவாக்கி, அவற்றை ஒரு குழாயில் இணைக்க வேண்டும் என்பதை பாஷ் அறிவார். மொத்தத்தில், பாஷுக்கு 2 குழந்தை செயல்முறைகள் மற்றும் ஒரு குழாய் தேவைப்படும்.

குழந்தை செயல்முறைகளை உருவாக்கும் முன் பாஷ் ஒரு கணினி அழைப்பை இயக்குகிறது குழாய் தற்காலிக பைப் பஃபரில் புதிய கோப்பு விளக்கங்களைப் பெறுகிறது, ஆனால் இந்த இடையகமானது எங்கள் இரு குழந்தை செயல்முறைகளை இன்னும் இணைக்கவில்லை.

பெற்றோர் செயல்முறைக்கு, ஏற்கனவே குழாய் இருப்பது போல் தெரிகிறது, ஆனால் குழந்தை செயல்முறைகள் எதுவும் இல்லை:

PID    command
15771  bash
lrwx------ 1 user user 64 Oct  7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:42 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:42 255 -> /dev/pts/21

பின்னர் கணினி அழைப்பைப் பயன்படுத்தவும் குளோன் பாஷ் இரண்டு குழந்தை செயல்முறைகளை உருவாக்குகிறது, மேலும் எங்கள் மூன்று செயல்முறைகள் இப்படி இருக்கும்:

PID    command
15771  bash
lrwx------ 1 user user 64 Oct  7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:42 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:42 255 -> /dev/pts/21
PID    command
9004  bash
lrwx------ 1 user user 64 Oct  7 15:57 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:57 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:57 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:57 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:57 255 -> /dev/pts/21
PID    command
9005  bash
lrwx------ 1 user user 64 Oct  7 15:57 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:57 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:57 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:57 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:57 255 -> /dev/pts/21

அனைத்து கோப்பு விளக்கங்களுடன் குளோன் செயல்முறையை குளோன் செய்கிறது என்பதை மறந்துவிடாதீர்கள், எனவே அவை பெற்றோர் செயல்முறையிலும் குழந்தைகளிலும் ஒரே மாதிரியாக இருக்கும். PID 15771 உடன் பெற்றோர் செயல்முறையின் வேலை குழந்தை செயல்முறைகளை கண்காணிப்பதாகும், எனவே அது குழந்தைகளின் பதிலுக்காக காத்திருக்கிறது.

எனவே, இதற்கு குழாய் தேவையில்லை, மேலும் இது 3 மற்றும் 4 எண் கொண்ட கோப்பு விளக்கங்களை மூடுகிறது.

PID 9004 உடன் முதல் குழந்தை பாஷ் செயல்பாட்டில், கணினி அழைப்பு dup2, எங்கள் STDOUT கோப்பு விளக்க எண் 1 ஐ பைப்பை சுட்டிக்காட்டும் கோப்பு விளக்கமாக மாற்றுகிறது, எங்கள் விஷயத்தில் இது எண் 3. எனவே, PID 9004 உடன் முதல் குழந்தை செயல்முறை STDOUT க்கு எழுதும் அனைத்தும் தானாகவே பைப் பஃபரில் முடிவடையும்.

PID 9005 உடன் இரண்டாவது குழந்தை செயல்பாட்டில், bash கோப்பு விளக்கமான STDIN எண் 2 ஐ மாற்ற dup0 ஐப் பயன்படுத்துகிறது. இப்போது PID 9005 உடன் நமது இரண்டாவது பாஷ் படிக்கும் அனைத்தும் பைப்பில் இருந்து படிக்கப்படும்.

இதற்குப் பிறகு, 3 மற்றும் 4 எண் கொண்ட கோப்பு விளக்கங்களும் குழந்தை செயல்முறைகளில் மூடப்படும், ஏனெனில் அவை இனி பயன்படுத்தப்படாது.

255 கோப்பு விளக்கத்தை நான் வேண்டுமென்றே புறக்கணிக்கிறேன்; இது பாஷ் மூலம் உள் நோக்கங்களுக்காகப் பயன்படுத்தப்படுகிறது மற்றும் குழந்தை செயல்முறைகளிலும் மூடப்படும்.

அடுத்து, PID 9004 உடன் முதல் குழந்தை செயல்பாட்டில், பாஷ் கணினி அழைப்பைப் பயன்படுத்தத் தொடங்குகிறது நினைவகத்தில் கட்டளை வரியில் நாம் குறிப்பிட்ட இயங்கக்கூடிய கோப்பு, எங்கள் விஷயத்தில் அது /usr/bin/cat ஆகும்.

PID 9005 உடன் இரண்டாவது குழந்தைச் செயல்பாட்டில், நாங்கள் குறிப்பிட்ட /usr/bin/sleep இல், bash இரண்டாவது இயங்கக்கூடியது.

திறந்த அழைப்பின் போது O_CLOEXEC கொடியுடன் திறக்கப்பட்டிருந்தால் தவிர, exec கணினி அழைப்பு கோப்பு கைப்பிடிகளை மூடாது. எங்கள் விஷயத்தில், இயங்கக்கூடிய கோப்புகளைத் தொடங்கிய பிறகு, தற்போதைய அனைத்து கோப்பு விளக்கங்களும் சேமிக்கப்படும்.

கன்சோலில் சரிபார்க்கவும்:

[user@localhost ]$ pgrep -P 15771
9004
9005
[user@localhost ]$ ls -lah /proc/15771/fd/
total 0
dr-x------ 2 user user  0 Oct  7 15:42 .
dr-xr-xr-x 9 user user  0 Oct  7 15:42 ..
lrwx------ 1 user user 64 Oct  7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:42 255 -> /dev/pts/21
[user@localhost ]$ ls -lah /proc/9004/fd
total 0
dr-x------ 2 user user  0 Oct  7 15:57 .
dr-xr-xr-x 9 user user  0 Oct  7 15:57 ..
lrwx------ 1 user user 64 Oct  7 15:57 0 -> /dev/pts/21
l-wx------ 1 user user 64 Oct  7 15:57 1 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:57 2 -> /dev/pts/21
lr-x------ 1 user user 64 Oct  7 15:57 3 -> /dev/zero
[user@localhost ]$ ls -lah /proc/9005/fd
total 0
dr-x------ 2 user user  0 Oct  7 15:57 .
dr-xr-xr-x 9 user user  0 Oct  7 15:57 ..
lr-x------ 1 user user 64 Oct  7 15:57 0 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct  7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct  7 15:57 2 -> /dev/pts/21
[user@localhost ]$ ps -up 9004
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
user  9004  0.0  0.0 107972   620 pts/21   S+   15:57   0:00 cat /dev/zero
[user@localhost ]$ ps -up 9005
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
user  9005  0.0  0.0 107952   360 pts/21   S+   15:57   0:00 sleep 10000

நீங்கள் பார்க்க முடியும் என, எங்கள் குழாயின் தனிப்பட்ட எண் இரண்டு செயல்முறைகளிலும் ஒரே மாதிரியாக இருக்கும். எனவே ஒரே பெற்றோருடன் இரண்டு வெவ்வேறு செயல்முறைகளுக்கு இடையே ஒரு தொடர்பு உள்ளது.

பாஷ் பயன்படுத்தும் சிஸ்டம் கால்களைப் பற்றித் தெரியாதவர்களுக்கு, ஸ்ட்ரேஸ் மூலம் கட்டளைகளை இயக்கவும், உள்நாட்டில் என்ன நடக்கிறது என்பதைப் பார்க்கவும் நான் மிகவும் பரிந்துரைக்கிறேன், எடுத்துக்காட்டாக இது போன்றது:

strace -s 1024 -f bash -c "ls | grep hello"

வட்டு இடம் தீர்ந்து, செயல்முறையை மறுதொடக்கம் செய்யாமல் டேட்டாவைச் சேமிக்க முயல்வது போன்ற நமது பிரச்சனைக்குத் திரும்புவோம். வட்டுக்கு வினாடிக்கு சுமார் 1 மெகாபைட் எழுதும் ஒரு சிறிய நிரலை எழுதுவோம். மேலும், சில காரணங்களால் வட்டில் தரவை எழுத முடியவில்லை என்றால், இதைப் புறக்கணித்து, ஒரு நொடியில் தரவை மீண்டும் எழுத முயற்சிப்போம். நான் பைத்தானைப் பயன்படுத்தும் எடுத்துக்காட்டில், நீங்கள் வேறு எந்த நிரலாக்க மொழியையும் பயன்படுத்தலாம்.

[user@localhost ]$ cat openforwrite.py 
import datetime
import time

mystr="a"*1024*1024+"n"
with open("123.txt", "w") as f:
    while True:
        try:
            f.write(str(datetime.datetime.now()))
            f.write(mystr)
            f.flush()
            time.sleep(1)
        except:
            pass

நிரலை இயக்கி, கோப்பு விளக்கங்களைப் பார்ப்போம்

[user@localhost ]$ python openforwrite.py &
[1] 3762
[user@localhost ]$ ps axuf | grep [o]penforwrite
user  3762  0.0  0.0 128600  5744 pts/22   S+   16:28   0:00  |   _ python openforwrite.py
[user@localhost ]$ ls -la /proc/3762/fd
total 0
dr-x------ 2 user user  0 Oct  7 16:29 .
dr-xr-xr-x 9 user user  0 Oct  7 16:29 ..
lrwx------ 1 user user 64 Oct  7 16:29 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  7 16:29 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  7 16:29 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  7 16:29 3 -> /home/user/123.txt

நீங்கள் பார்க்க முடியும் என, எங்களிடம் 3 நிலையான கோப்பு விளக்கங்கள் உள்ளன, மேலும் நாங்கள் திறக்கப்பட்ட ஒன்று உள்ளது. கோப்பின் அளவைச் சரிபார்ப்போம்:

[user@localhost ]$ ls -lah 123.txt 
-rw-rw-r-- 1 user user 117M Oct  7 16:30 123.txt

தரவு எழுதப்படுகிறது, கோப்பில் உள்ள அனுமதிகளை மாற்ற முயற்சிக்கிறோம்:

[user@localhost ]$ sudo chown root: 123.txt
[user@localhost ]$ ls -lah 123.txt 
-rw-rw-r-- 1 root root 168M Oct  7 16:31 123.txt
[user@localhost ]$ ls -lah 123.txt 
-rw-rw-r-- 1 root root 172M Oct  7 16:31 123.txt

கோப்பில் எழுதுவதற்கு எங்கள் பயனருக்கு அனுமதி இல்லை என்றாலும், தரவு இன்னும் எழுதப்படுவதைக் காண்கிறோம். அதை அகற்ற முயற்சிப்போம்:

[user@localhost ]$ sudo rm 123.txt 
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory

தரவு எங்கே எழுதப்பட்டுள்ளது? மேலும் அவை எழுதப்பட்டதா? நாங்கள் சரிபார்க்கிறோம்:

[user@localhost ]$ ls -la /proc/3762/fd
total 0
dr-x------ 2 user user  0 Oct  7 16:29 .
dr-xr-xr-x 9 user user  0 Oct  7 16:29 ..
lrwx------ 1 user user 64 Oct  7 16:29 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  7 16:29 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  7 16:29 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  7 16:29 3 -> /home/user/123.txt (deleted)

ஆம், எங்கள் கோப்பு விளக்கி இன்னும் உள்ளது, மேலும் இந்த கோப்பு விளக்கத்தை நமது பழைய கோப்பைப் போலவே கருதலாம், அதைப் படிக்கலாம், அழிக்கலாம் மற்றும் நகலெடுக்கலாம்.

கோப்பின் அளவைப் பார்ப்போம்:

[user@localhost ]$ lsof | grep 123.txt
python    31083             user    3w      REG                8,5   19923457   2621522 /home/user/123.txt

கோப்பின் அளவு 19923457. கோப்பை அழிக்க முயற்சிப்போம்:

[user@localhost ]$ truncate -s 0 /proc/31083/fd/3
[user@localhost ]$ lsof | grep 123.txt
python    31083             user    3w      REG                8,5  136318390   2621522 /home/user/123.txt

நீங்கள் பார்க்க முடியும் என, கோப்பு அளவு மட்டுமே அதிகரித்து வருகிறது மற்றும் எங்கள் டிரங்க் வேலை செய்யவில்லை. கணினி அழைப்பு ஆவணத்தைப் பார்ப்போம் திறந்த. ஒரு கோப்பைத் திறக்கும் போது O_APPEND கொடியைப் பயன்படுத்தினால், ஒவ்வொரு எழுதும் போதும், இயக்க முறைமை கோப்பு அளவைச் சரிபார்த்து, கோப்பின் இறுதிவரை தரவை எழுதுகிறது, மேலும் இதை அணுசக்தியாகச் செய்கிறது. இது ஒரே கோப்பில் பல இழைகள் அல்லது செயல்முறைகளை எழுத அனுமதிக்கிறது. ஆனால் எங்கள் குறியீட்டில் இந்த கொடியை நாங்கள் பயன்படுத்துவதில்லை. கூடுதல் எழுத்துக்காக கோப்பைத் திறந்தால் மட்டுமே டிரங்குக்குப் பிறகு lsof இல் வேறு கோப்பு அளவைக் காண முடியும், அதற்குப் பதிலாக நமது குறியீட்டில்

with open("123.txt", "w") as f:

நாம் வைக்க வேண்டும்

with open("123.txt", "a") as f:

"w" கொடியுடன் சரிபார்க்கிறது

[user@localhost ]$ strace -e trace=open python openforwrite.py 2>&1| grep 123.txt
open("123.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

மற்றும் "அ" கொடியுடன்

[user@localhost ]$ strace -e trace=open python openforwrite.py 2>&1| grep 123.txt
open("123.txt", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

ஏற்கனவே இயங்கும் செயல்முறை நிரலாக்கம்

பெரும்பாலும் புரோகிராமர்கள், நிரல்களை உருவாக்கி சோதனை செய்யும் போது, ​​பிழைத்திருத்தங்கள் (உதாரணமாக GDB) அல்லது பயன்பாட்டில் பல்வேறு நிலைகளில் உள்நுழைவதைப் பயன்படுத்துகின்றனர். லினக்ஸ் ஏற்கனவே இயங்கும் நிரலை எழுதுவதற்கும் மாற்றுவதற்கும் திறனை வழங்குகிறது, எடுத்துக்காட்டாக, மாறிகளின் மதிப்புகளை மாற்றவும், முறிவு புள்ளியை அமைக்கவும், முதலியன.

ஒரு கோப்பை எழுத போதுமான வட்டு இடம் இல்லை என்ற அசல் கேள்விக்கு திரும்பினால், சிக்கலை உருவகப்படுத்த முயற்சிப்போம்.

எங்கள் பகிர்வுக்கு ஒரு கோப்பை உருவாக்குவோம், அதை தனி வட்டாக ஏற்றுவோம்:

[user@localhost ~]$ dd if=/dev/zero of=~/tempfile_for_article.dd bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00525929 s, 2.0 GB/s
[user@localhost ~]$

ஒரு கோப்பு முறைமையை உருவாக்குவோம்:

[user@localhost ~]$ mkfs.ext4 ~/tempfile_for_article.dd
mke2fs 1.42.9 (28-Dec-2013)
/home/user/tempfile_for_article.dd is not a block special device.
Proceed anyway? (y,n) y
...
Writing superblocks and filesystem accounting information: done
[user@localhost ~]$

கோப்பு முறைமையை ஏற்றவும்:

[user@localhost ~]$ sudo mount ~/tempfile_for_article.dd /mnt/
[sudo] password for user: 
[user@localhost ~]$ df -h | grep mnt
/dev/loop0      8.7M  172K  7.9M   3% /mnt

எங்கள் உரிமையாளருடன் ஒரு கோப்பகத்தை உருவாக்குகிறோம்:

[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs

எங்கள் நிரலில் எழுதுவதற்கு மட்டுமே கோப்பைத் திறப்போம்:

with open("/mnt/logs/123.txt", "w") as f:

தொடங்கு

[user@localhost ]$ python openforwrite.py 

நாங்கள் சில வினாடிகள் காத்திருக்கிறோம்

[user@localhost ~]$ df -h | grep mnt
/dev/loop0      8.7M  8.0M     0 100% /mnt

எனவே, இந்த கட்டுரையின் ஆரம்பத்தில் விவரிக்கப்பட்டுள்ள சிக்கலை நாங்கள் கொண்டுள்ளோம். இலவச இடம் 0, 100% ஆக்கிரமிக்கப்பட்டுள்ளது.

பணியின் நிபந்தனைகளின்படி, இழக்க முடியாத மிக முக்கியமான தரவை பதிவு செய்ய முயற்சிக்கிறோம் என்பதை நாங்கள் நினைவில் கொள்கிறோம். அதே நேரத்தில், செயல்முறையை மறுதொடக்கம் செய்யாமல் சேவையை சரிசெய்ய வேண்டும்.

நம்மிடம் இன்னும் வட்டு இடம் உள்ளது என்று வைத்துக்கொள்வோம், ஆனால் வேறு பகிர்வில், எடுத்துக்காட்டாக /home இல்.

எங்கள் குறியீட்டை "பறக்கும்போது மறு நிரல்" செய்ய முயற்சிப்போம்.

எங்கள் செயல்முறையின் PID ஐப் பார்ப்போம், இது அனைத்து வட்டு இடத்தையும் சாப்பிட்டது:

[user@localhost ~]$ ps axuf | grep [o]penfor
user 10078 27.2  0.0 128600  5744 pts/22   R+   11:06   0:02  |   _ python openforwrite.py

ஜிடிபி வழியாக செயல்முறையுடன் இணைக்கவும்

[user@localhost ~]$ gdb -p 10078
...
(gdb) 

திறந்த கோப்பு விளக்கங்களைப் பார்ப்போம்:

(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user  0 Oct  8 11:06 .
dr-xr-xr-x 9 user user  0 Oct  8 11:06 ..
lrwx------ 1 user user 64 Oct  8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:09 3 -> /mnt/logs/123.txt

எங்களுக்கு விருப்பமான கோப்பு விளக்க எண் 3 பற்றிய தகவலைப் பார்க்கிறோம்

(gdb) shell cat /proc/10078/fdinfo/3
pos:    8189952
flags:  0100001
mnt_id: 482

Python என்ன சிஸ்டம் கால் செய்கிறது என்பதை மனதில் வைத்து (மேலே பார்க்கவும், நாம் strace ஓடி திறந்த அழைப்பைக் கண்டோம்), ஒரு கோப்பைத் திறக்க, எங்கள் குறியீட்டைச் செயலாக்கும்போது, ​​எங்கள் செயல்முறையின் சார்பாக நாமே அதையே செய்கிறோம், ஆனால் நமக்கு O_WRONLY|O_CREAT| O_TRUNC பிட்கள் ஒரு எண் மதிப்புடன் மாற்றப்படும். இதைச் செய்ய, எடுத்துக்காட்டாக, கர்னல் மூலங்களைத் திறக்கவும் இங்கே மற்றும் எந்தெந்த கொடிகள் எதற்குப் பொறுப்பு என்று பாருங்கள்

# தவறான 00000001 ஐ வரையறுக்கவும்
#O_CREAT 00000100 ஐ வரையறுக்கவும்
#O_TRUNC 00001000 ஐ வரையறுக்கவும்

எல்லா மதிப்புகளையும் ஒன்றாக இணைக்கிறோம், 00001101 ஐப் பெறுகிறோம்

நாங்கள் எங்கள் அழைப்பை gdb இலிருந்து இயக்குகிறோம்

(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4

எனவே எண் 4 உடன் ஒரு புதிய கோப்பு விளக்கத்தையும் மற்றொரு பகிர்வில் புதிய திறந்த கோப்பையும் பெற்றுள்ளோம், நாங்கள் சரிபார்க்கிறோம்:

(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user  0 Oct  8 11:06 .
dr-xr-xr-x 9 user user  0 Oct  8 11:06 ..
lrwx------ 1 user user 64 Oct  8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:09 3 -> /mnt/logs/123.txt
l-wx------ 1 user user 64 Oct  8 11:15 4 -> /home/user/123.txt

பைப் மூலம் உதாரணத்தை நாங்கள் நினைவில் கொள்கிறோம் - பாஷ் கோப்பு விளக்கங்களை எவ்வாறு மாற்றுகிறது, மேலும் நாங்கள் ஏற்கனவே dup2 கணினி அழைப்பைக் கற்றுக்கொண்டோம்.

ஒரு கோப்பு விளக்கத்தை மற்றொரு கோப்புடன் மாற்ற முயற்சிக்கிறோம்

(gdb) call dup2(4,3)
$2 = 3

பார்க்கலாம்:

(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user  0 Oct  8 11:06 .
dr-xr-xr-x 9 user user  0 Oct  8 11:06 ..
lrwx------ 1 user user 64 Oct  8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:09 3 -> /home/user/123.txt
l-wx------ 1 user user 64 Oct  8 11:15 4 -> /home/user/123.txt

கோப்பு விளக்கம் 4 ஐ மூடுகிறோம், ஏனெனில் இது தேவையில்லை:

(gdb) call close (4)
$1 = 0

மற்றும் ஜிடிபியிலிருந்து வெளியேறவும்

(gdb) quit
A debugging session is active.

    Inferior 1 [process 10078] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2.7, process 10078

புதிய கோப்பை சரிபார்க்கிறது:

[user@localhost ~]$ ls -lah /home/user/123.txt
-rw-rw-r-- 1 user user 5.1M Oct  8 11:18 /home/user/123.txt
[user@localhost ~]$ ls -lah /home/user/123.txt
-rw-rw-r-- 1 user user 7.1M Oct  8 11:18 /home/user/123.txt

நீங்கள் பார்க்க முடியும் என, தரவு ஒரு புதிய கோப்பில் எழுதப்பட்டுள்ளது, பழையதை சரிபார்க்கலாம்:

[user@localhost ~]$ ls -lah /mnt/logs/123.txt 
-rw-rw-r-- 1 user user 7.9M Oct  8 11:08 /mnt/logs/123.txt

தரவு எதுவும் இழக்கப்படவில்லை, பயன்பாடு வேலை செய்கிறது, பதிவுகள் புதிய இடத்திற்கு எழுதப்படும்.

பணியை கொஞ்சம் சிக்கலாக்குவோம்

தரவு நமக்கு முக்கியமானது என்று கற்பனை செய்து கொள்வோம், ஆனால் எந்த பகிர்வுகளிலும் வட்டு இடம் இல்லை, மேலும் வட்டை இணைக்க முடியாது.

நாம் செய்யக்கூடியது, நமது தரவை எங்காவது திருப்பிவிடுவது, எடுத்துக்காட்டாக, குழாய்க்கு அனுப்புவது, மேலும் சில நிரல்களின் மூலம் குழாயிலிருந்து பிணையத்திற்குத் தரவைத் திருப்பிவிடுவது, எடுத்துக்காட்டாக நெட்கேட்.
mkfifo கட்டளை மூலம் பெயரிடப்பட்ட பைப்பை உருவாக்கலாம். கோப்பு முறைமையில் இலவச இடம் இல்லாவிட்டாலும் அது ஒரு போலி கோப்பை உருவாக்கும்.

பயன்பாட்டை மறுதொடக்கம் செய்து சரிபார்க்கவும்:

[user@localhost ]$ python openforwrite.py 
[user@localhost ~]$ ps axuf | grep [o]pen
user  5946 72.9  0.0 128600  5744 pts/22   R+   11:27   0:20  |   _ python openforwrite.py
[user@localhost ~]$ ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user  0 Oct  8 11:27 .
dr-xr-xr-x 9 user user  0 Oct  8 11:27 ..
lrwx------ 1 user user 64 Oct  8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:28 3 -> /mnt/logs/123.txt
[user@localhost ~]$ df -h | grep mnt
/dev/loop0      8.7M  8.0M     0 100% /mnt

வட்டு இடம் இல்லை, ஆனால் ஒரு பெயரிடப்பட்ட குழாயை வெற்றிகரமாக உருவாக்குகிறோம்:

[user@localhost ~]$ mkfifo /mnt/logs/megapipe
[user@localhost ~]$ ls -lah /mnt/logs/megapipe 
prw-rw-r-- 1 user user 0 Oct  8 11:28 /mnt/logs/megapipe

இப்போது இந்த குழாயில் செல்லும் அனைத்து தரவையும் நெட்வொர்க் வழியாக மற்றொரு சேவையகத்திற்கு எப்படியாவது மடிக்க வேண்டும்; அதே நெட்கேட் இதற்கு ஏற்றது.

remote-server.example.com என்ற சர்வரில் நாங்கள் தொடங்குகிறோம்

[user@localhost ~]$ nc -l 7777 > 123.txt 

எங்கள் பிரச்சனை சர்வரில் நாங்கள் ஒரு தனி முனையத்தில் தொடங்குகிறோம்

[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe 

இப்போது குழாயில் முடிவடையும் எல்லா தரவும் தானாகவே netcat இல் stdin க்கு செல்லும், அது போர்ட் 7777 இல் உள்ள பிணையத்திற்கு அனுப்பும்.

நாம் செய்ய வேண்டியதெல்லாம், இந்த பெயரிடப்பட்ட பைப்பில் நமது தரவை எழுதத் தொடங்குவதுதான்.

எங்களிடம் ஏற்கனவே பயன்பாடு இயங்குகிறது:

[user@localhost ~]$ ps axuf | grep [o]pen
user  5946 99.8  0.0 128600  5744 pts/22   R+   11:27 169:27  |   _ python openforwrite.py
[user@localhost ~]$ ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user  0 Oct  8 11:27 .
dr-xr-xr-x 9 user user  0 Oct  8 11:27 ..
lrwx------ 1 user user 64 Oct  8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:28 3 -> /mnt/logs/123.txt

எல்லா கொடிகளிலும், கோப்பு ஏற்கனவே இருப்பதால், அதை அழிக்க வேண்டிய அவசியமில்லை என்பதால், எங்களுக்கு O_WRONLY மட்டுமே தேவை.

[user@localhost ~]$ gdb -p 5946
...
(gdb) call open("/mnt/logs/megapipe", 00000001,0666)
$1 = 4
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user  0 Oct  8 11:27 .
dr-xr-xr-x 9 user user  0 Oct  8 11:27 ..
lrwx------ 1 user user 64 Oct  8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:28 3 -> /mnt/logs/123.txt
l-wx------ 1 user user 64 Oct  8 14:20 4 -> /mnt/logs/megapipe
(gdb) call dup2(4,3)
$2 = 3
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user  0 Oct  8 11:27 .
dr-xr-xr-x 9 user user  0 Oct  8 11:27 ..
lrwx------ 1 user user 64 Oct  8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:28 3 -> /mnt/logs/megapipe
l-wx------ 1 user user 64 Oct  8 14:20 4 -> /mnt/logs/megapipe
(gdb) call close(4)
$3 = 0
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user  0 Oct  8 11:27 .
dr-xr-xr-x 9 user user  0 Oct  8 11:27 ..
lrwx------ 1 user user 64 Oct  8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct  8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct  8 11:28 3 -> /mnt/logs/megapipe
(gdb) quit
A debugging session is active.

    Inferior 1 [process 5946] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2.7, process 5946

ரிமோட் சர்வர் remote-server.example.com ஐச் சரிபார்க்கிறது

[user@localhost ~]$ ls -lah 123.txt 
-rw-rw-r-- 1 user user 38M Oct  8 14:21 123.txt

தரவு வருகிறது, சிக்கல் சேவையகத்தைச் சரிபார்க்கிறோம்

[user@localhost ~]$ ls -lah /mnt/logs/
total 7.9M
drwxr-xr-x 2 user user 1.0K Oct  8 11:28 .
drwxr-xr-x 4 root     root     1.0K Oct  8 10:55 ..
-rw-rw-r-- 1 user user 7.9M Oct  8 14:17 123.txt
prw-rw-r-- 1 user user    0 Oct  8 14:22 megapipe

தரவு சேமிக்கப்படுகிறது, சிக்கல் தீர்க்கப்படுகிறது.

டெகிரோவைச் சேர்ந்த எனது சக ஊழியர்களுக்கு வணக்கம் சொல்ல இந்த வாய்ப்பைப் பயன்படுத்துகிறேன்.
ரேடியோ-டி பாட்காஸ்ட்களைக் கேளுங்கள்.

அனைவருக்கும் நல்லது.

வீட்டுப்பாடமாக, நீங்கள் பின்வரும் கட்டளையை இயக்கினால், பூனை மற்றும் தூக்கத்தை விவரிக்கும் செயல்முறை கோப்பில் என்ன இருக்கும் என்பதைப் பற்றி சிந்திக்க பரிந்துரைக்கிறேன்:

[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000

ஆதாரம்: www.habr.com

கருத்தைச் சேர்