ãã®èšäºã§ã¯ãUnix ã«ãŒãã«ã§ã®ãã€ãã©ã€ã³ã®å®è£
ã«ã€ããŠèª¬æããŸãã æè¿ã®ãããšããã¿ã€ãã«ã®èšäºã«å°ããã£ããããŸããã
äœããïŒ
ãã€ãã©ã€ã³ã¯ããããã Unix ã§æãéèŠãªçºæãã§ããããã¯ãå°ããªããã°ã©ã ããŸãšãããšãã Unix ã®æ ¹åºã«ããå²åŠã®ç¹åŸŽã§ãããããç¥ãããã³ãã³ãã©ã€ã³ã®ã¹ããŒã¬ã³ã§ãã
$ echo hello | wc -c
6
ãã®æ©èœã¯ãã«ãŒãã«ãæäŸããã·ã¹ãã ã³ãŒã«ã«äŸåããŸãã pipe
ãããã¥ã¡ã³ãããŒãžã§èª¬æãããŠããŸã
ãã€ãã©ã€ã³ã¯ãããã»ã¹ééä¿¡ã®ããã®äžæ¹åãã£ãã«ãæäŸããŸãã ãã€ãã©ã€ã³ã«ã¯å ¥å (æžã蟌ã¿åŽ) ãšåºå (èªã¿åãåŽ) ããããŸãã ãã€ãã©ã€ã³ã®å ¥åã«æžã蟌ãŸããããŒã¿ã¯ãåºåã§èªã¿åãããšãã§ããŸãã
ãã€ãã©ã€ã³ã¯åŒã³åºãã«ãã£ãŠäœæãããŸã
pipe(2)
ããã㯠XNUMX ã€ã®ãã¡ã€ã«èšè¿°åãè¿ããŸããXNUMX ã€ã¯ãã€ãã©ã€ã³ã®å ¥åãåç §ããXNUMX ã€ç®ã¯åºåãåç §ããŸãã
äžèšã®ã³ãã³ãããã®ãã¬ãŒã¹åºåã¯ããã€ãã©ã€ã³ã®äœæãšããããéãããããã»ã¹ããå¥ã®ããã»ã¹ãžã®ããŒã¿ã®æµãã瀺ããŠããŸãã
$ 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()
æ·»ä»ãã¡ã€ã«èšè¿°åãååŸããŸãã 2 ã€ã®åããã»ã¹ã 3 ã€ã®èšè¿°åã«æžã蟌ã¿ãå¥ã®ããã»ã¹ãå¥ã®èšè¿°åããåãããŒã¿ãèªã¿åããŸãã ã·ã§ã«ã¯ãstdin ãš stdout ã«äžèŽããããã«ãdup4 ã䜿çšããŠèšè¿°å XNUMX ãš XNUMX ããååå€æŽãããŸãã
ãã€ãã©ã€ã³ããªããã°ãã·ã§ã«ã¯ XNUMX ã€ã®ããã»ã¹ã®åºåããã¡ã€ã«ã«æžã蟌ã¿ããããå¥ã®ããã»ã¹ã«ãã€ãããŠãã¡ã€ã«ããããŒã¿ãèªã¿åãå¿ èŠããããŸãã ãã®çµæãããå€ãã®ãªãœãŒã¹ãšãã£ã¹ã¯é åãç¡é§ã«ãªããŸãã ãã ãããã€ãã©ã€ã³ã¯äžæãã¡ã€ã«ãåé¿ããã ãã§ã¯ãããŸããã
ããã»ã¹ã空ã®ãã€ãã©ã€ã³ããèªã¿åãããšãããšã
read(2)
ããŒã¿ãå©çšå¯èœã«ãªããŸã§ãããã¯ãããŸãã ããã»ã¹ãå®å šãªãã€ãã©ã€ã³ã«æžã蟌ãããšãããšãwrite(2)
æžã蟌ã¿ãå®äºããã®ã«ååãªããŒã¿ããã€ãã©ã€ã³ããèªã¿åããããŸã§ãããã¯ãããŸãã
POSIX èŠä»¶ãšåæ§ãããã¯éèŠãªããããã£ã§ãããã€ãã©ã€ã³ãžã®æžã蟌ã¿ã¯æ¬¡ã®ãšããã§ãã PIPE_BUF
éåžžã®ãã¡ã€ã« (ãã®ãããªä¿èšŒã¯ãããŸãã) ã§ã¯äžå¯èœãªæ¹æ³ã§ããã»ã¹ããã€ãã©ã€ã³ãä»ããŠçžäºã«éä¿¡ã§ããããã«ããã€ã (å°ãªããšã 512) ã¯ã¢ãããã¯ã§ããå¿
èŠããããŸãã
éåžžã®ãã¡ã€ã«ã䜿çšãããšãããã»ã¹ã¯ãã¹ãŠã®åºåããã®ãã¡ã€ã«ã«æžã蟌ã¿ããããå¥ã®ããã»ã¹ã«æž¡ãããšãã§ããŸãã ãŸãã¯ãããã»ã¹ã¯ãå€éšä¿¡å·ã¡ã«ããºã (ã»ããã©ãªã©) ã䜿çšããŠãæžã蟌ã¿ãŸãã¯èªã¿åãã®å®äºãçžäºã«éç¥ããããŒã䞊åã¢ãŒãã§åäœããããšãã§ããŸãã ã³ã³ãã€ãŒã䜿ãã°ãããããç ©ããããã解æŸãããŸãã
ç§ãã¡ã¯äœãæ¢ããŠããã®ã§ããããïŒ
ã³ã³ãã¢ã®ä»çµã¿ãã€ã¡ãŒãžããããããã«æã䜿ã£ãŠèª¬æããŸãã ã¡ã¢ãªå ã«ãããã¡ãšäœããã®ç¶æ ãå²ãåœãŠãå¿ èŠããããŸãã ãããã¡ãŒã«ããŒã¿ãè¿œå ãããããããã¡ãŒããããŒã¿ãåé€ãããããé¢æ°ãå¿ èŠã«ãªããŸãã ãã¡ã€ã«èšè¿°åã®èªã¿åãããã³æžã蟌ã¿æäœäžã«é¢æ°ãåŒã³åºãããã®äœããã®æ©èœãå¿ èŠã«ãªããŸãã ãŸããäžèšã®ç¹å¥ãªåäœãå®è£ ããã«ã¯ããã¯ãå¿ èŠã§ãã
ããã§ãç§ãã¡ã®ææ§ãªã¡ã³ã¿ã« ã¢ãã«ã確èªãŸãã¯å蚌ããããã«ãæããã©ã³ãã®å ã®äžã§ã«ãŒãã«ã®ãœãŒã¹ ã³ãŒãã調æ»ããæºåãæŽããŸããã ããããåžžã«äºæãã¬äºæ ã«åããŠãã ããã
ç§ãã¡ã¯ã©ããèŠãŠããã®ã§ããããïŒ
ç§ã®æåãªæ¬ã®ã³ããŒãã©ãã«ãããããããŸããã
TUHS ã®ã¢ãŒã«ã€ããæ£çããã®ã¯ããŸãã§åç©é€šã蚪ããŠãããã®ããã§ãã ç§ãã¡ã¯ç§ãã¡ã®å ±æã®æŽå²ãæ¯ãè¿ãããšãã§ããå€ãã«ã»ãããããªã³ãã¢ãŠããããã®è³æãã¹ãŠãå°ããã€åŸ©å ããé·å¹Žã®åªåã«æ¬æãè¡šããŸãã ãããŠãç§ã¯ãŸã æ¬ ããŠããæçãçæããŠããŸãã
ãã€ãã©ã€ã³ã®å€ä»£ã®æŽå²ã«ã€ããŠã®å¥œå¥å¿ãæºããããã®ã§ãæ¯èŒã®ããã«çŸä»£ã®ã³ã¢ãèŠãŠã¿ãŸãããã
ãšããã§ã pipe
ããŒãã«å
ã®ã·ã¹ãã ã³ãŒã«çªå· 42 ã§ãã sysent[]
ã äžèŽïŒ
åŸæ¥ã® Unix ã«ãŒãã« (1970 ïœ 1974 幎)
çè·¡ã¯èŠã€ãããŸããã§ãã pipe(2)
ã©ã¡ãã§ããªã
TUHSã¯æ¬¡ã®ããã«äž»åŒµããŠãã
Unix ã®ç¬¬ 1973 çã¯ãã¢ã»ã³ãã©ã§æžãããã«ãŒãã«ãåããæåŸã®ããŒãžã§ã³ã§ãããããã€ãã©ã€ã³ãåããæåã®ããŒãžã§ã³ã§ããããŸããã XNUMX 幎ã«ç¬¬ XNUMX çãæ¹è¯ããäœæ¥ãé²ããããã«ãŒãã«ã C ã§æžãçŽãããUnix ã®ç¬¬ XNUMX çãèªçããŸããã
ããèªè ã¯ããã°ã»ãããã€ããåºã®ããŒã¹ã®ããã«ããã°ã©ã ãæ¥ç¶ããããšããã¢ã€ãã¢ãææ¡ããææžã®ã¹ãã£ã³ãèŠã€ããã
ãã©ã€ã¢ã³ã»ã«ãŒããã³ã®æ¬ã®äžã§
Unix ãç»å Žãããšããã³ã«ãŒãã³ã«å¯Ÿããç§ã®æ ç±ãããããããã»ã¹ã«æžã蟌ãŸããããŒã¿ãããã€ã¹ã ãã§ãªãå¥ã®ããã»ã¹ã®åºå£ã«ãéä¿¡ã§ããããã«ãããããOS äœè ã® Ken Thompson ã«äŸé ŒããŸããã ã±ã³ã¯ãããå¯èœã ãšèããã ããããããããªã¹ããšããŠã圌ã¯ãã¹ãŠã®ã·ã¹ãã æ©èœãéèŠãªåœ¹å²ãæããããšãæãã§ããŸããã ããã»ã¹éã®çŽæ¥æžã蟌ã¿ã¯ãäžéãã¡ã€ã«ãžã®æžã蟌ã¿ã«æ¯ã¹ãŠæ¬åœã«å€§ããªå©ç¹ãããã®ã§ãããã? ãããŠãç§ãããã€ãã©ã€ã³ããšãããã£ãããŒãªååãšããã»ã¹ã®çžäºäœçšã®æ§æã®èª¬æã䜿ã£ãŠå ·äœçãªææ¡ããããšãããããã Ken ã¯ãç§ããããŸã!ããšå«ã³ãŸããã
ãããŠãããããŸããã ããéåœçãªå€ãã±ã³ã¯ã«ãŒãã«ãšã·ã§ã«ãå€æŽããããã€ãã®æšæºããã°ã©ã ãä¿®æ£ããŠå ¥å (ãã€ãã©ã€ã³ããæ¥ãå¯èœæ§ããã) ã®åãå ¥ãæ¹æ³ãæšæºåãããã¡ã€ã«åãå€æŽããŸããã ç¿æ¥ããã€ãã©ã€ã³ã¯ã¢ããªã±ãŒã·ã§ã³ã§éåžžã«åºã䜿çšãããããã«ãªããŸããã é±æ«ãŸã§ã«ãç§æžãã¡ã¯ææžãã¯ãŒããããããªã³ã¿ãŒã«éä¿¡ããããã«ãããã䜿çšããŸããã å°ãåŸãKen ã¯ãã€ãã©ã€ã³ã®äœ¿çšãã©ããããããã®å ã® API ãšæ§æãããã以æ¥äœ¿çšãããŠããããã¯ãªãŒã³ãªèŠåã«çœ®ãæããŸããã
æ®å¿µãªããã第 XNUMX ç Unix ã«ãŒãã«ã®ãœãŒã¹ ã³ãŒãã¯å€±ãããŠããŸãã ã«ãŒãã«ã®ãœãŒã¹ã³ãŒã㯠C ã§æžãããŠããŸããã
ã®ããã¥ã¡ã³ãããã¹ãããããŸã pipe(2)
äž¡æ¹ã®ãªãªãŒã¹ããæäŸãããŠãããããããã¥ã¡ã³ããæ€çŽ¢ããããšããå§ããããšãã§ããŸãã pipe(2)
ããã¯ã¢ã»ã³ãã©ã§æžãããŠããããã¡ã€ã«èšè¿°åã XNUMX ã€ã ãè¿ããŸãããæåŸ
ãããã³ã¢æ©èœã¯ãã§ã«æäŸãããŠããŸãã
ã·ã¹ãã ã³ãŒã« ãã€ã ãã€ãã©ã€ã³ãšåŒã°ãã I/O ã¡ã«ããºã ãäœæããŸãã è¿ããããã¡ã€ã«èšè¿°åã¯ãèªã¿åãããã³æžã蟌ã¿æäœã«äœ¿çšã§ããŸãã ãã€ãã©ã€ã³ã«äœããæžã蟌ãŸãããšããã€ãã©ã€ã³ã¯æ倧 504 ãã€ãã®ããŒã¿ããããã¡ãªã³ã°ãããã®åŸæžã蟌ã¿ããã»ã¹ãäžæåæ¢ãããŸãã ãã€ãã©ã€ã³ããèªã¿åãå Žåããããã¡ãªã³ã°ãããããŒã¿ãååŸãããŸãã
ç¿å¹ŽãŸã§ã«ã«ãŒãã«ã¯ C ã§æžãçŽããã pipe(fildes)
»ïŒ
ã·ã¹ãã ã³ãŒã« ãã€ã ãã€ãã©ã€ã³ãšåŒã°ãã I/O ã¡ã«ããºã ãäœæããŸãã è¿ããããã¡ã€ã«èšè¿°åã¯ãèªã¿åãããã³æžã蟌ã¿æäœã§äœ¿çšã§ããŸãã ãã€ãã©ã€ã³ã«äœããæžã蟌ãŸãããšãr1 ã§è¿ãããèšè¿°å (ãããã fildes[1]) ã䜿çšãããæ倧 4096 ãã€ãã®ããŒã¿ããããã¡ãªã³ã°ããããã®åŸæžã蟌ã¿ããã»ã¹ãäžæåæ¢ãããŸãã ãã€ãã©ã€ã³ããèªã¿åãå Žåãr0 ã«è¿ãããèšè¿°å (ãããã fildes[0]) ãããŒã¿ãåãåããŸãã
ãã€ãã©ã€ã³ãå®çŸ©ããããšãXNUMX 〠(ãŸãã¯ãã以äž) ã®å¯Ÿè©±ããã»ã¹ (åŸç¶ã®åŒã³åºãã«ãã£ãŠäœæããã) ãå®è¡ããããšæ³å®ãããŸãã ãã©ãŒã¯) åŒã³åºãã䜿çšããŠãã€ãã©ã€ã³ããããŒã¿ãæž¡ããŸã read О æžããŸã.
ã·ã§ã«ã«ã¯ããã€ãã©ã€ã³ãä»ããŠæ¥ç¶ãããããã»ã¹ã®ç·åœ¢é åãå®çŸ©ããããã®æ§æããããŸãã
ãšã³ãã XNUMX ã€ã ã (ãã¹ãŠã®æžã蟌ã¿ãã¡ã€ã«èšè¿°åãéããŠãã) 空ã®ãã€ãã©ã€ã³ (ãããã¡ãªã³ã°ãããããŒã¿ãå«ãŸãªã) ããã®èªã¿åããåŒã³åºããšãããã¡ã€ã«ã®çµããããè¿ãããŸãã åæ§ã®ç¶æ³ã§ã®æžã蟌ã¿åŒã³åºãã¯ç¡èŠãããŸãã
æå€ã®
Unix 第 1975 ç (XNUMX)
Unix ãœãŒã¹ã³ãŒããèªã¿å§ãã
é·å¹Žã«ãããããã®æ¬ã¯ ã©ã€ãªã³ ããã¯ããã«ç 究æ以å€ã§å ¥æå¯èœãª Unix ã«ãŒãã«ã«é¢ããå¯äžã®ææžã§ããã 第 XNUMX çã®ã©ã€ã»ã³ã¹ã§ã¯æåž«ããã®ãœãŒã¹ ã³ãŒãã䜿çšããããšãèš±å¯ãããŠããŸãããã第 XNUMX çã®ã©ã€ã»ã³ã¹ã§ã¯ãã®å¯èœæ§ãé€å€ãããŠããããããã®æ¬ã¯éæ³ã«ã¿ã€ãæã¡ãããã³ããŒã§é åžãããŸããã
çŸåšããã®æ¬ã®åççã賌å
¥ã§ããŸããè¡šçŽã«ã¯ã³ããŒæ©ã«åããåŠçãæãããŠããŸãã ãããŠãWarren Toomey (TUHS ãããžã§ã¯ããå§ãã人) ã®ãããã§ãããŠã³ããŒãã§ããããã«ãªããŸããã
15 幎以äžåãç§ã¯ãæäŸãããŠãããœãŒã¹ ã³ãŒãã®ã³ããŒãå ¥åããŸããã ã©ã€ãªã³ãªããªããä»ã®æ°ãåããªãã»ã©ã®ã³ããŒã®ãã¡ãèªåã®ã³ããŒã®å質ãæ°ã«å ¥ããªãã£ãããã§ãã TUHS ã¯ãŸã ååšããŠããããç§ã¯å€ãæ å ±æºã«ã¢ã¯ã»ã¹ã§ããŸããã§ããã ããã 1988 幎ã«ãPDP9 ã³ã³ãã¥ãŒã¿ããããã¯ã¢ããããã 11 ãã©ãã¯ã®å€ãããŒããèŠã€ããŸããã ãããæ©èœãããã©ãããç¥ãã®ã¯å°é£ã§ããããç¡å·ã® /usr/src/ ããªãŒãååšããã»ãšãã©ã®ãã¡ã€ã«ã«ã¯ 1979 幎ãšããŒã¯ãããŠãããåœæããèŠãŠãå€ããã®ã«èŠããŸããã ããã¯ç¬¬ XNUMX çããŸã㯠PWB ã®æŽŸççã ãšæããŸããã
ç§ã¯ãã®çºèŠãåºç€ãšããŠãœãŒã¹ã第 XNUMX çã®ç¶æ ã«æåã§ç·šéããŸããã ã³ãŒãã®äžéšã¯åããŸãŸã§ãããäžéšãå°ãç·šéããå¿ èŠããããææ°ã®ããŒã¯ã³ += ãå»æ¢ããã =+ ã«å€æŽããŸããã äœããåçŽã«åé€ãããäœããå®å šã«æžãçŽãå¿ èŠããããŸãããã倧ããããšã¯ãããŸããã§ããã
ãããŠä»æ¥ãç§ãã¡ã¯TUHSã§ãªã³ã©ã€ã³ã§ã第XNUMXçã®ãœãŒã¹ã³ãŒããèªãããšãã§ããŸãã
ãšããã§ãã«ãŒããã³ãšãªãããŒã®æ代以åã® C ã³ãŒãã®äž»ãªç¹åŸŽã¯ãäžèŠãããšæ¬¡ã®ãšããã§ãã ç°¡æœã ãµã€ãäžã®æ¯èŒççã衚瀺é åã«åãããŠå€§èŠæš¡ãªç·šéãè¡ããã«ã³ãŒãã®ã¹ãããããæ¿å ¥ã§ããããšã¯ãããŸããããŸããã
æ©ã
/*
* 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
ãããã¡ãµã€ãºã¯ç¬¬ XNUMX çããå€æŽãããŠããŸããã ããããããã§ã¯ãå ¬éææžã¯äœããããŸãããããã€ãã©ã€ã³ããã€ãŠãã¡ã€ã«ããã©ãŒã«ãã㯠ã¹ãã¬ãŒãžãšããŠäœ¿çšããŠããããšãããããŸãã
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;
}
ã³ã¡ã³ãã¯ããã§äœãèµ·ãã£ãŠããããæ確ã«èª¬æããŠããŸãã ããããã³ãŒããç解ããã®ã¯ããã»ã©ç°¡åã§ã¯ãããŸããããã®çç±ã® XNUMX ã€ã¯ãR0
О R1
ã·ã¹ãã ã³ãŒã«ãã©ã¡ãŒã¿ãšæ»ãå€ãæž¡ãããŸãã
è©ŠããŠã¿ãŸããã
pipe()
æéãŸã§ã« R0
О R1
èªã¿åãããã³æžã蟌ã¿çšã®ãã¡ã€ã«èšè¿°åçªå·ãè¿ããŸãã falloc()
ãã¡ã€ã«æ§é ãžã®ãã€ã³ã¿ãè¿ããŸãããçµç±ã§ãè¿ããããšãã§ããŸãã u.u_ar0[R0]
ãããŠãã¡ã€ã«èšè¿°åã ã€ãŸããã³ãŒãã¯æ¬¡ã®ããã«ä¿åãããŸãã r
èªã¿åãçšã®ãã¡ã€ã«èšè¿°åãšãçŽæ¥æžã蟌ã¿çšã®èšè¿°åãå²ãåœãŠãŸãã u.u_ar0[R0]
XNUMXåç®ã®éè©±åŸ falloc()
.
Ѐлаг FPIPE
ãã€ãã©ã€ã³ã®äœææã«èšå®ããé¢æ°ã®åäœãå¶åŸ¡ããŸã
/*
* 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
ã ãŸããi ããŒããããã¯ããå¿
èŠããããŸã (以äžãåç
§) plock
/prele
).
次ã«ãinode åç
§æ°ã確èªããŸãã ãã€ãã©ã€ã³ã®äž¡ç«¯ãéãããŸãŸã§ããéããã«ãŠã³ã¿ã¯ 2 ã«ãªãã¯ãã§ãã XNUMX ã€ã®ãªã³ã¯ãä¿æããŸã (ãã rp->f_inode
) ãªã®ã§ãã«ãŠã³ã¿ãŒã 2 æªæºã®å Žåã¯ãèªã¿åãããã»ã¹ããã€ãã©ã€ã³ã®çµç«¯ãéããããšãæå³ããŸãã èšãæããã°ãéãããã€ãã©ã€ã³ã«æžã蟌ãããšããŠããã®ã§ãããããã¯ééãã§ãã æåã®ãšã©ãŒã³ãŒã EPIPE
ãããŠä¿¡å· SIGPIPE
Unix ã®ç¬¬ XNUMX çã«ç»å ŽããŸããã
ãã ããã³ã³ãã¢ãéããŠããŠããæºæ¯ã®å ŽåããããŸãã ãã®å Žåãå¥ã®ããã»ã¹ããã€ãã©ã€ã³ããèªã¿åãããã€ãã©ã€ã³å ã«ååãªã¹ããŒã¹ã解æŸããããšãæåŸ ããŠãããã¯ã解æŸããŠã¹ãªãŒãç¶æ ã«å ¥ããŸãã ç®èŠãããšãæåã«æ»ããåã³ããã¯ã解é€ããæ°ããæžã蟌ã¿ãµã€ã¯ã«ãéå§ããŸãã
ãã€ãã©ã€ã³ã«ååãªç©ºãé åãããå Žåã¯ã次ã䜿çšããŠããã«ããŒã¿ãæžã蟌ã¿ãŸãã i_size1
inode'a (空ã®ãã€ãã©ã€ã³ã§ã¯ 0 ã«çãããŠããã) ã¯ããã§ã«å«ãŸããŠããããŒã¿ã®çµãããæããŸãã æžã蟌ãã®ã«ååãªã¹ããŒã¹ãããå Žåã¯ã次ãããã€ãã©ã€ã³ãåããããšãã§ããŸãã i_size1
ЎП PIPESIZ
ã 次ã«ãããã¯ã解æŸãããã€ãã©ã€ã³ããã®èªã¿åããåŸ
æ©ããŠããããã»ã¹ãèµ·åããããšããŸãã æåã«æ»ã£ãŠãå¿
èŠãªã ãã®ãã€ããæžã蟌ãããšãã§ãããã©ããã確èªããŸãã 倱æããå Žåã¯ãæ°ããèšé²ãµã€ã¯ã«ãéå§ããŸãã
éåžžãã©ã¡ãŒã¿ i_mode
i ããŒãã¯æš©éãä¿åããããã«äœ¿çšãããŸã r
, w
О x
ã ãããããã€ãã©ã€ã³ã®å Žåã¯ããããã䜿çšããŠãäžéšã®ããã»ã¹ãæžã蟌ã¿ãŸãã¯èªã¿åããåŸ
ã£ãŠããããšãéç¥ããŸãã IREAD
О IWRITE
ããããã ããã»ã¹ã¯ãã©ã°ãèšå®ããŠåŒã³åºããŸãã sleep()
ããããŠå°æ¥çã«ã¯ä»ã®ããã»ã¹ãåŒã³åºãããšãäºæ³ãããŸã wakeup()
.
æ¬åœã®éæ³ãèµ·ããã®ã¯ã sleep()
О wakeup()
ã å®è£
ãããŠããã®ã¯ã
/*
* 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);
}
ãã®é¢æ°ã¯äžããäžã«èªããšèªã¿ããããããããŸããã ãèªã¿åããšåŸ©åž°ããã©ã³ãã¯éåžžããã€ãã©ã€ã³ã«ããŒã¿ãããå Žåã«äœ¿çšãããŸãã ãã®å Žåã䜿çšããã®ã¯ã f_offset
察å¿ãããªãã»ããã®å€ãèªã¿åããæŽæ°ããŸãã
åŸç¶ã®èªã¿åãã§ã¯ãèªã¿åããªãã»ããã«éãããšãã€ãã©ã€ã³ã¯ç©ºã«ãªããŸãã i_size1
i ããŒãã§ã äœçœ®ã 0 ã«ãªã»ãããããã€ãã©ã€ã³ã«æžã蟌ã¿ããããã»ã¹ããŠã§ã€ã¯ã¢ããããããšããŸãã ã³ã³ãã¢ããã£ã±ãã«ãªããšã writep()
ã«ç ããŸã ip+1
ã ãã€ãã©ã€ã³ã空ã«ãªã£ãã®ã§ããã€ãã©ã€ã³ãèµ·åããŠæžã蟌ã¿ãµã€ã¯ã«ãåéã§ããŸãã
èªããã®ããªãå Žåã¯ã readp()
ãã©ã°ãç«ãŠãããšãã§ãã IREAD
ãããŠç ãã«ã€ã ip+2
ã äœã圌ãç®èŠããããã®ãç§ãã¡ã¯ç¥ã£ãŠããŸã writep()
ãã€ãã©ã€ã³ã«ããŒã¿ãæžã蟌ããšãã
ã³ã¡ã³ã 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()
i ããŒããçµäºãããçµæãååŸãããŸã§ããã¯ããŸã (ã€ãŸããåŒã³åºã 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()
ãµã€ã¯ã«ãåéããŸãã
以äžã§ç¬¬ XNUMX çã®ãã€ãã©ã€ã³ã«ã€ããŠã®èª¬æãçµãããŸãã ã·ã³ãã«ãªã³ãŒããåºç¯å²ã«ããã圱é¿ã
Xv6ãåçŽãª Unix 颚ã®ã«ãŒãã«
æ žãäœæããã«ã¯
ã³ãŒãã«ã¯æ確ã§ææ
®æ·±ãå®è£
ãå«ãŸããŠããŸã 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
ã§å®è£
ãããã©ãããŒã§ã
Linux 0.01
Linux 0.01 ã®ãœãŒã¹ ã³ãŒããèŠã€ããããšãã§ããŸãã 圌ã®èæžã§ãã€ãã©ã€ã³ã®å®è£
ãç 究ããããšã¯æçã§ãã fs
/pipe.c
ã ããã§ã¯ããã€ãã©ã€ã³ãè¡šãããã« i ããŒãã䜿çšãããŠããŸããããã€ãã©ã€ã³èªäœã¯ææ°ã® C ã§æžãããŠããŸãã第 XNUMX çã®ã³ãŒãããããã³ã°ããããšãããã°ãããã§ã¯äœã®åé¡ããããŸããã æ©èœã¯ãããªæãã§ã 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;
}
æ§é äœã®å®çŸ©ãèŠãªããŠããæžã蟌ã¿æäœã®çµæã以äžã§ãããã©ããã確èªããããã« inode åç
§ã«ãŠã³ããã©ã®ããã«äœ¿çšãããããç解ã§ããŸãã SIGPIPE
ã ãã®é¢æ°ã¯ãã€ãåäœã®äœæ¥ã«å ããŠãäžèšã®ã¢ã€ãã¢ãšæ¯èŒããã®ãç°¡åã§ãã å¶æ°ããžã㯠sleep_on
/wake_up
ãããªã«ç°æ人ã«ã¯èŠããŸããã
ææ°ã® Linux ã«ãŒãã«ãFreeBSDãNetBSDãOpenBSD
ç§ã¯ããã€ãã®ææ°ã®ã«ãŒãã«ãç°¡åã«èª¿ã¹ãŸããã ãããã®ã©ããããã§ã«ãã£ã¹ã¯ããŒã¹ã®å®è£ ãæã£ãŠããŸãã (åœç¶ã®ããšã§ãã)ã Linux ã«ã¯ç¬èªã®å®è£ ããããŸãã ãããŠãXNUMX ã€ã®ææ°ã® BSD ã«ãŒãã«ã«ã¯ãJohn Dyson ã«ãã£ãŠæžãããã³ãŒãã«åºã¥ãå®è£ ãå«ãŸããŠããŸãããé·å¹Žã®éã«ããããã¯äºãã«ããŸãã«ãç°ãªã£ãŠããŸããã
èªãã«ã¯ fs
/pipe.c
(Linux ã®å Žå) ãŸã㯠sys
/kern
/sys_pipe.c
(*BSD ã§ã¯)ãããã«ã¯çã®ç®èº«ãå¿
èŠã§ãã ä»æ¥ã®ã³ãŒãã§ã¯ãããã©ãŒãã³ã¹ãšãã¯ãã«ãéåæ I/O ãªã©ã®æ©èœã®ãµããŒããéèŠã§ãã ãŸããã¡ã¢ãªå²ãåœãŠãããã¯ãã«ãŒãã«æ§æã®è©³çŽ°ã¯ãã¹ãŠå€§ããç°ãªããŸãã ããã¯å€§åŠããªãã¬ãŒãã£ã³ã° ã·ã¹ãã ã®å
¥éã³ãŒã¹ã«å¿
èŠãšãããã®ã§ã¯ãããŸããã
ãããã«ãããããã€ãã®å€ããã¿ãŒã³ãçºæããã®ã¯èå³æ·±ãããšã§ãã (ããšãã°ã SIGPIPE
ãããŠæ»ã EPIPE
éãããã€ãã©ã€ã³ã«æžã蟌ãå Žå)ãããããã¹ãŠã®éåžžã«ç°ãªãææ°ã®ã«ãŒãã«ã§ã PDP-11 ã³ã³ãã¥ãŒã¿ãŒãå®éã«èŠãããšã¯ãããããªãã§ãããããç§ãçãŸããæ°å¹Žåã«æžãããã³ãŒãããåŠã¶ã¹ãããšã¯ãŸã ãããããããŸãã
2011 幎ã«ãã£ãŽã£ã»ã«ããŒã«ã«ãã£ãŠæžãããèšäºã
åºæïŒ habr.com