
рдкрд░рд┐рдЪрдп
I / O рд░рд┐рдПрдХреНрдЯрд░ (рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рдЗрд╡реЗрдВрдЯ рд▓реВрдк ) рдЕрддреНрдпрдзрд┐рдХ рд▓реЛрдб рдХрд┐рдП рдЧрдП рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреИрдЯрд░реНрди рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдИ рд▓реЛрдХрдкреНрд░рд┐рдп рд╕рдорд╛рдзрд╛рдиреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо I / O рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рдЗрдиреНрд╕ рдФрд░ рдмрд╣рд┐рд╖реНрдХрд╛рд░ рдФрд░ рдЗрд╕рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ, рдХреЛрдб рдХреА 200 рд╕реЗ рдХрдо рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рд┐рдЦреЗрдВ рдФрд░ рдПрдХ рд╕рд╛рдзрд╛рд░рдг HTTP рд╕рд░реНрд╡рд░ рдХреЛ 40 рдорд┐рд▓рд┐рдпрди рд╕реЗ рдЕрдзрд┐рдХ рдЕрдиреБрд░реЛрдзреЛрдВ / рдорд┐рдирдЯ рдкрд░ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдХрд░реЗрдВред
рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛
- рд▓реЗрдЦ I / O рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рдХрд╛рдордХрд╛рдЬ рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдЬреЛрдЦрд┐рдореЛрдВ рдХрд╛ рдПрд╣рд╕рд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
- рд▓реЗрдЦ рдореЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реА рднрд╛рд╖рд╛ рдХреА рдореВрд▓ рдмрд╛рддреЛрдВ рдХрд╛ рдЬреНрдЮрд╛рди рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЕрдиреБрднрд╡ рдЖрд╡рд╢реНрдпрдХ рд╣реИред
- рд╕рднреА рдХреЛрдб рд╕реА рдореЗрдВ рд╕рдЦреНрддреА рд╕реЗ ( рд╕рд╛рд╡рдзрд╛рдиреА рд╕реЗ: рд▓рдВрдмреЗ рдкреАрдбреАрдПрдл ) рд▓рд┐рдирдХреНрд╕ рдХреЗ рд▓рд┐рдП C11 рдорд╛рдирдХ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВ рдФрд░ GitHub рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ ред
рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ?
рдЗрдВрдЯрд░рдиреЗрдЯ рдХреА рдмрдврд╝рддреА рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рдХреЗ рд╕рд╛рде, рд╡реЗрдм рд╕рд░реНрд╡рд░ рдХреЛ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХрдиреЗрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП рджреЛ рджреГрд╖реНрдЯрд┐рдХреЛрдгреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЧрдИ рдереА: рдПрдХ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдУрдПрд╕ рдереНрд░реЗрдбреНрд╕ рдкрд░ рдЕрд╡рд░реБрджреНрдз I / O рдФрд░ рдПрдХ рдЗрд╡реЗрдВрдЯ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз I / O, рдЬрд┐рд╕реЗ "рд╕рд┐рд╕реНрдЯрдо" рднреА рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЪрдпрдирдХрд░реНрддрд╛ "( epoll / kqueue / IOCP / etc)ред
рдкреНрд░рддреНрдпреЗрдХ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдУрдПрд╕ рдереНрд░реЗрдб рдмрдирд╛рдиреЗ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдкрд╣рд▓рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдгред рдЗрд╕рдХрд╛ рдиреБрдХрд╕рд╛рди рдЦрд░рд╛рдм рд╕реНрдХреЗрд▓реЗрдмрд┐рд▓рд┐рдЯреА рд╣реИ: рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдХрдИ рд╕рдВрджрд░реНрдн рдкрд░рд┐рд╡рд░реНрддрди рдФрд░ рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ ред рд╡реЗ рдорд╣рдВрдЧреЗ рдСрдкрд░реЗрд╢рди рд╣реИрдВ рдФрд░ рдХрдиреЗрдХреНрд╢рди рдХреА рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдореБрдлреНрдд рд░реИрдо рдХреА рдХрдореА рд╣реЛ рд╕рдХрддреА рд╣реИред
рд╕рдВрд╢реЛрдзрд┐рдд рд╕рдВрд╕реНрдХрд░рдг рдереНрд░реЗрдбреНрд╕ (рдереНрд░реЗрдб рдкреВрд▓) рдХреА рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдВрдЦреНрдпрд╛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддрд╛ рд╣реИ , рдЬрд┐рд╕рд╕реЗ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдЕрд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рд░реЛрдХрдирд╛ рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд╛рде рд╣реА рд╕рд╛рде рдПрдХ рдирдИ рд╕рдорд╕реНрдпрд╛ рднреА рдкреЗрд╢ рдХрд░рддрд╛ рд╣реИ: рдпрджрд┐ рджрд┐рдП рдЧрдП рд╕рдордп рдкрд░ рдереНрд░реЗрдб рдкреВрд▓ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдкрдврд╝рдиреЗ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рд╕реЗ рдЕрд╡рд░реБрджреНрдз рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЕрдиреНрдп рдкреЙрдХреЗрдЯ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рджреВрд╕рд░рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЗрд╡реЗрдВрдЯ рд╕реВрдЪрдирд╛ рдкреНрд░рдгрд╛рд▓реА (рд╕рд┐рд╕реНрдЯрдо рдЪрдпрдирдХрд░реНрддрд╛) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдУрдПрд╕ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд▓реЗрдЦ рдЖрдИ / рдУ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рддрддреНрдкрд░рддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрд▓рд░реНрдЯ (рдШрдЯрдирд╛рдУрдВ, рд╕реВрдЪрдирд╛рдУрдВ) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рдмрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд┐рд╕реНрдЯрдо рдЪрдпрдирдХрд░реНрддрд╛ рдХреА рдЪрд░реНрдЪрд╛ рдХрд░рддрд╛ рд╣реИ, рдмрдЬрд╛рдп рдЙрдирдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрд▓рд░реНрдЯ рдХреЗ ред рдЗрд╕рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд╛ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝реНрд▓реЛрдЪрд╛рд░реНрдЯ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

рдЗрди рддрд░реАрдХреЛрдВ рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
- I / O рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд░рдирд╛ рддрдм рддрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдЯреНрд░реАрдо рдХреЛ рдирд┐рд▓рдВрдмрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ OS рдЖрдиреЗ рд╡рд╛рд▓реА IP рдкреИрдХреЗрдЯ рдХреЛ рдмрд╛рдЗрдЯ рд╕реНрдЯреНрд░реАрдо ( TCP , рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛) рдореЗрдВ рдареАрдХ рд╕реЗ рдбреАрдлрд╝реНрд░реЗрдЧреНрдореЗрдВрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдПрдирдЖрдИрд╕реА (рдбреЗрдЯрд╛ рднреЗрдЬрдирд╛) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдВрддрд░рд┐рдХ рд░рд╛рдЗрдЯ рдмрдлрд╝рд░реНрд╕ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рд╕реНрдерд╛рди рдЦрд╛рд▓реА рдХрд░ рджреЗрддрд╛ рд╣реИред
- рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж, рд╕рд┐рд╕реНрдЯрдо рдЪрдпрдирдХрд░реНрддрд╛ рдЙрд╕ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдУрдПрд╕ рдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЖрдИрдкреА тАЛтАЛрдкреИрдХреЗрдЯ (рдЯреАрд╕реАрдкреА, рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛) рдХреЛ рдбреАрдлрд╝реНрд░реИрдЧреНрдореЗрдиреНрдЯ рдХрд░ рджрд┐рдпрд╛ рд╣реИ рдпрд╛ рдЖрдВрддрд░рд┐рдХ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдмрдлрд╝рд░реНрд╕ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рдЬрдЧрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдкрд▓рдмреНрдз рд╣реИ (рдбреЗрдЯрд╛ рднреЗрдЬ рд░рд╣рд╛ рд╣реИ)ред
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ I / O рдХреЗ рд▓рд┐рдП OS рдереНрд░реЗрдб рдХреЛ рдЬрдорд╛ рдХрд░рдирд╛ рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ рд╢рдХреНрддрд┐ рдХреА рдмрд░реНрдмрд╛рджреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдереНрд░реЗрдбреНрд╕ рдЙрдкрдпреЛрдЧреА рдХрд╛рд░реНрдп рдХреЗ рд╕рд╛рде рд╡реНрдпрд╕реНрдд рдирд╣реАрдВ рд╣реИрдВ (рд╢рдмреНрдж "рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд░реБрдХрд╛рд╡рдЯ" рдореЗрдВ рдЗрд╕рдХреА рдЬрдбрд╝реЗрдВ рд╣реИрдВ )ред рд╕рд┐рд╕реНрдЯрдо рдЪрдпрдирдХрд░реНрддрд╛ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рд╕реАрдкреАрдпреВ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХрд╛ рдЕрдзрд┐рдХ рдЖрд░реНрдерд┐рдХ рд░реВрдк рд╕реЗ рдЙрдкрднреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рд░рд┐рдПрдХреНрдЯрд░ I / O рдореЙрдбрд▓
I / O рд░рд┐рдПрдХреНрдЯрд░ рд╕рд┐рд╕реНрдЯрдо рдЪрдпрдирдХрд░реНрддрд╛ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдХреЗ рдмреАрдЪ рдПрдХ рдкрд░рдд рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рд╕рд┐рджреНрдзрд╛рдВрдд рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлреНрд▓реЛрдЪрд╛рд░реНрдЯ рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рд╣реИ:

- рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдПрдХ рдШрдЯрдирд╛ рдПрдХ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рд╣реИ рдХрд┐ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕реЙрдХреЗрдЯ рдПрдХ рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз I / O рдСрдкрд░реЗрд╢рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИред
- рдПрдХ рдЗрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬрд┐рд╕реЗ I / O рд░рд┐рдПрдХреНрдЯрд░ рджреНрд╡рд╛рд░рд╛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдХреЛрдИ рдИрд╡реЗрдВрдЯ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рддрдм рдПрдХ рдиреЙрди-рдмреНрд▓реЙрдХрд┐рдВрдЧ I / O рдСрдкрд░реЗрд╢рди рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ I / O рд░рд┐рдПрдХреНрдЯрд░ рдкрд░рд┐рднрд╛рд╖рд╛ рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╣реИ, рд▓реЗрдХрд┐рди 1 рд╕реНрдЯреНрд░реАрдо: 1 рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рд░реЛрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рд╕рднреА рд╕реАрдкреАрдпреВ рдХреЛрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реЛрддрд╛ рд╣реИред
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
рд╣рдордиреЗ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ reactor.h
рдлрд╝рд╛рдЗрд▓, рдФрд░ reactor.c
рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ reactor.c
ред reactor.h
рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдШреЛрд╖рдгрд╛рдПрдБ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреА:
рд░рд┐рдПрдХреНрдЯрд░ рдореЗрдВ рд╡рд┐рдЬреНрдЮрд╛рдкрди рджрд┐рдЦрд╛рдПрдВ typedef struct reactor Reactor; typedef void (*Callback)(void *arg, int fd, uint32_t events); Reactor *reactor_new(void); int reactor_destroy(Reactor *reactor); int reactor_register(const Reactor *reactor, int fd, uint32_t interest, Callback callback, void *callback_arg); int reactor_deregister(const Reactor *reactor, int fd); int reactor_reregister(const Reactor *reactor, int fd, uint32_t interest, Callback callback, void *callback_arg); int reactor_run(const Reactor *reactor, time_t timeout);
рд░рд┐рдПрдХреНрдЯрд░ рдХреА I / O рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдПрдХ рдПрдкреЛрд▓ рдЪрдпрдирдХрд░реНрддрд╛ рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдФрд░ рдПрдХ GHashTable
рд╣реИрд╢ рддрд╛рд▓рд┐рдХрд╛ рд╣реИ , рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд╕реЙрдХреЗрдЯ рдореИрдкреНрд╕ GHashTable
(рдПрдХ рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рд╕реЗ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рддрд░реНрдХ) рдХреЗ рд╣реЛрддреЗ рд╣реИрдВред
рд░рд┐рдПрдХреНрдЯрд░ рдФрд░ рдХреЙрд▓рдмреИрдХрдбреЗрдЯрд╛ рджрд┐рдЦрд╛рдПрдВ struct reactor { int epoll_fd; GHashTable *table;
рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдордиреЗ рд╕реВрдЪрдХ рджреНрд╡рд╛рд░рд╛ рдЕрдкреВрд░реНрдг рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред reactor.h
рд╣рдо reactor
рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ reactor.c
рдЗрд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрдкрдиреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдмрджрд▓рдиреЗ рд╕реЗ рд░реЛрдХрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдбреЗрдЯрд╛ рдЫрд┐рдкрд╛рдиреЗ рдХреЗ рдкреИрдЯрд░реНрди рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ рдЬреЛ рд╕реА рдХреЗ рд╢рдмреНрджрд╛рд░реНрде рдореЗрдВ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рд░реВрдк рд╕реЗ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИред
reactor_register
, reactor_deregister
рдФрд░ reactor_reregister
, рд╕рд┐рд╕реНрдЯрдо рд╕рд┐рд▓реЗрдХреНрдЯрд░ рдФрд░ рд╣реИрд╢ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдШрдЯрдирд╛ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдХреЗ рд╕реЙрдХреЗрдЯреНрд╕ рдХреА рд╕реВрдЪреА рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВред
рдкрдВрдЬреАрдХрд░рдг рд╕реБрд╡рд┐рдзрд╛рдПрдБ рджрд┐рдЦрд╛рдПрдВ #define REACTOR_CTL(reactor, op, fd, interest) \ if (epoll_ctl(reactor->epoll_fd, op, fd, \ &(struct epoll_event){.events = interest, \ .data = {.fd = fd}}) == -1) { \ perror("epoll_ctl"); \ return -1; \ } int reactor_register(const Reactor *reactor, int fd, uint32_t interest, Callback callback, void *callback_arg) { REACTOR_CTL(reactor, EPOLL_CTL_ADD, fd, interest) g_hash_table_insert(reactor->table, int_in_heap(fd), callback_data_new(callback, callback_arg)); return 0; } int reactor_deregister(const Reactor *reactor, int fd) { REACTOR_CTL(reactor, EPOLL_CTL_DEL, fd, 0) g_hash_table_remove(reactor->table, &fd); return 0; } int reactor_reregister(const Reactor *reactor, int fd, uint32_t interest, Callback callback, void *callback_arg) { REACTOR_CTL(reactor, EPOLL_CTL_MOD, fd, interest) g_hash_table_insert(reactor->table, int_in_heap(fd), callback_data_new(callback, callback_arg)); return 0; }
I / O рд░рд┐рдПрдХреНрдЯрд░ fd
рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЗ рд╕рд╛рде рдИрд╡реЗрдВрдЯ рдХреЛ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЗрд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХрд╣рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдпрд╣ fd
рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИ, рдЬреЗрдирд░реЗрдЯ рдХреА рдЧрдИ рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдмрд┐рдЯ рдорд╛рд╕реНрдХ рдФрд░ void
рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпреВрдЬрд░ рдкреЙрдЗрдВрдЯрд░ред
рджрд┐рдЦрд╛рдПрдБ рд░рд┐рдПрдХреНрдЯрд░_рд░реБрди () рдлрд╝рдВрдХреНрд╢рди int reactor_run(const Reactor *reactor, time_t timeout) { int result; struct epoll_event *events; if ((events = calloc(MAX_EVENTS, sizeof(*events))) == NULL) abort(); time_t start = time(NULL); while (true) { time_t passed = time(NULL) - start; int nfds = epoll_wait(reactor->epoll_fd, events, MAX_EVENTS, timeout - passed); switch (nfds) {
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд░реВрдк рд▓реЗрдЧреА:

рд╕рд┐рдВрдЧрд▓ рдереНрд░реЗрдбреЗрдб рд╕рд░реНрд╡рд░
рдЙрдЪреНрдЪ рднрд╛рд░ рдХреЗ рддрд╣рдд I / O рд░рд┐рдПрдХреНрдЯрд░ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдЫрд╡рд┐ рдХреЗ рд╕рд╛рде рдХрд┐рд╕реА рднреА рдЕрдиреБрд░реЛрдз рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ HTTP рд╡реЗрдм рд╕рд░реНрд╡рд░ рд▓рд┐рдЦреЗрдВрдЧреЗред
HTTP рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рддреНрд╡рд░рд┐рдд рд╕рдВрджрд░реНрднHTTP рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди-рд╕реНрддрд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╣реИ рдЬреЛ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЗ рд╕рд╛рде рд╕рд░реНрд╡рд░ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
HTTP рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдЯреАрд╕реАрдкреА рдкрд░рд┐рд╡рд╣рди рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдкреНрд░рд╛рд░реВрдк рдХреЗ рд╕рдВрджреЗрд╢ рднреЗрдЬрдирд╛ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ред
<> <URI> < HTTP>CRLF < 1>CRLF < 2>CRLF < N>CRLF CRLF <>
CRLF
рджреЛ рд╡рд░реНрдгреЛрдВ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реИ: \r
рдФрд░ \n
, рдХреНрд╡реЗрд░реА, рд╣реЗрдбрд░ рдФрд░ рдбреЗрдЯрд╛ рдХреА рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдХреЛ рдЕрд▓рдЧ рдХрд░рддрд╛ рд╣реИред<>
CONNECT
, DELETE
, GET
, HEAD
, OPTIONS
, PATCH
, POST
, PUT
, TRACE
ред рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╣рдорд╛рд░реЗ рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ GET
рдХрдорд╛рдВрдб рднреЗрдЬреЗрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ "рдореБрдЭреЗ рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рднреЗрдЬреЗрдВред"<URI>
рдПрдХреАрдХреГрдд рд╕рдВрд╕рд╛рдзрди рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рд╣реИ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ URI = /index.html
, рддреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдЯ рдХреЗ рдореБрдЦреНрдп рдкреГрд╖реНрда рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИред< HTTP>
- HTTP/XY
рдкреНрд░рд╛рд░реВрдк рдореЗрдВ HTTP/XY
рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╕рдВрд╕реНрдХрд░рдгред рдЕрдм рддрдХ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рд╕рдВрд╕реНрдХрд░рдг HTTP/1.1
ред< N>
рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдПрдХ рдкреНрд░рдореБрдЦ-рдореВрд▓реНрдп рд╡рд╛рд▓рд╛ рдЬреЛрдбрд╝рд╛ рд╣реИ <>: <>
, рдЬреЛ рдЖрдЧреЗ рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдХреЛ рднреЗрдЬрд╛ рдЧрдпрд╛ рд╣реИред<>
- рдСрдкрд░реЗрд╢рди рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рджреНрд╡рд╛рд░рд╛ рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛ред рдЕрдХреНрд╕рд░ рдпрд╣ рд╕рд┐рд░реНрдл JSON рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╣реЛрддрд╛ рд╣реИред
< HTTP> < > < >CRLF < 1>CRLF < 2>CRLF < N>CRLF CRLF <>
< >
рдПрдХ рдСрдкрд░реЗрд╢рди рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рд╕рдВрдЦреНрдпрд╛ рд╣реИред рд╣рдорд╛рд░рд╛ рд╕рд░реНрд╡рд░ рд╣рдореЗрд╢рд╛ рд╕реНрдерд┐рддрд┐ 200 (рд╕рдлрд▓ рд╕рдВрдЪрд╛рд▓рди) рд▓реМрдЯрд╛рдПрдЧрд╛ред< >
- рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ред рд╕реНрдерд┐рддрд┐ рдХреЛрдб 200 рдХреЗ рд▓рд┐рдП, рдпрд╣ OK
ред< N>
- рдЕрдиреБрд░реЛрдз рдореЗрдВ рдЙрд╕реА рдкреНрд░рд╛рд░реВрдк рдХрд╛ рд╢реАрд░реНрд╖рд▓реЗрдЦред рд╣рдо Content-Length
(рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЖрдХрд╛рд░) рдФрд░ Content-Type: text/html
(рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ рдбреЗрдЯрд╛) рд╢реАрд░реНрд╖ Content-Type: text/html
рд▓реМрдЯрд╛рдПрдВрдЧреЗред<>
- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд░реЛрдзрд┐рдд рдбреЗрдЯрд╛ред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ HTML рдореЗрдВ рдЫрд╡рд┐ рдХрд╛ рдорд╛рд░реНрдЧ рд╣реИред
http_server.c
(рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╕рд░реНрд╡рд░) рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдПрдХ common.h
рдлрд╝рд╛рдЗрд▓ рд╢рд╛рдорд┐рд▓ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдирд┐рдореНрди рдлрд╝рдВрдХреНрд╢рди рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:
рдлрдВрдХреНрд╢рди рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдореЗрдВ рджрд┐рдЦрд╛рдПрдБ static void on_accept(void *arg, int fd, uint32_t events); static void on_send(void *arg, int fd, uint32_t events); static void on_recv(void *arg, int fd, uint32_t events); static void set_nonblocking(int fd); static noreturn void fail(const char *format, ...); static int new_server(bool reuse_port);
рдлрд╝рдВрдХреНрд╢рди рдореИрдХреНрд░реЛ SAFE_CALL()
рднреА рд╡рд░реНрдгрд┐рдд рд╣реИ рдФрд░ fail()
рдлрд╝рдВрдХреНрд╢рди рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реИред рдореИрдХреНрд░реЛ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдореВрд▓реНрдп рдХреА рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рд╢рд░реНрдд рдкреВрд░реА рд╣реЛ рдЬрд╛рддреА рд╣реИ, рддреЛ рдпрд╣ fail()
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ:
#define SAFE_CALL(call, error) \ do { \ if ((call) == error) { \ fail("%s", #call); \ } \ } while (false)
fail()
рдлрдВрдХреНрд╢рди, рдкрд╛рд╕ рдХрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЛ рдЯрд░реНрдорд┐рдирд▓ (рдЬреИрд╕реЗ EXIT_FAILURE
fail()
рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИ рдФрд░ EXIT_FAILURE
рдХреЛрдб рдХреЗ рд╕рд╛рде рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ:
static noreturn void fail(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, ": %s\n", strerror(errno)); exit(EXIT_FAILURE); }
new_server()
рдлрд╝рдВрдХреНрд╢рди рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ socket()
, bind()
рдФрд░ listen()
рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдИ рдЧрдИ "рд╕рд░реНрд╡рд░" рд╕реЙрдХреЗрдЯ рдХреА рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдФрд░ рдЧреИрд░-рдЕрд╡рд░реЛрдзрдХ рдореЛрдб рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХрдиреЗрдХреНрд╢рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИред
рдлрд╝рдВрдХреНрд╢рди рджрд┐рдЦрд╛рдПрдВ new_server () static int new_server(bool reuse_port) { int fd; SAFE_CALL((fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP)), -1); if (reuse_port) { SAFE_CALL( setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)), -1); } struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(SERVER_PORT), .sin_addr = {.s_addr = inet_addr(SERVER_IPV4)}, .sin_zero = {0}}; SAFE_CALL(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), -1); SAFE_CALL(listen(fd, SERVER_BACKLOG), -1); return fd; }
- рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕реЙрдХреЗрдЯ рд╢реБрд░реВ рдореЗрдВ
SOCK_NONBLOCK
рдзреНрд╡рдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧреИрд░-рдЕрд╡рд░реЛрдзрдХ рдореЛрдб рдореЗрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддрд╛рдХрд┐ on_accept()
рдлрд╝рдВрдХреНрд╢рди (рдФрд░ рдкрдврд╝реЗрдВ) рдореЗрдВ, accept()
рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рд╕реНрдЯреНрд░реАрдо рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рд░реЛрдХ рди рд╕рдХреЗред - рдпрджрд┐
reuse_port
true
, рддреЛ рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд╕реЙрдХреЗрдЯ рдХреЛ рдПрдХ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рд╕рдорд╛рди рдкреЛрд░реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП setsockopt()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ SO_REUSEPORT
рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдЧрд╛ (рдЕрдиреБрднрд╛рдЧ "рдорд▓реНрдЯреА-рдереНрд░реЗрдбреЗрдб рд╕рд░реНрд╡рд░" рджреЗрдЦреЗрдВ)ред
on_accept()
рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЛ рддрдм рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм OS EPOLLIN
рдИрд╡реЗрдВрдЯ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдПрдХ рдирдпрд╛ рдХрдиреЗрдХреНрд╢рди рд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред on_accept()
рдПрдХ рдирдП рдХрдиреЗрдХреНрд╢рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕реЗ рдЧреИрд░-рдЕрд╡рд░реЛрдзрдХ рдореЛрдб рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рддрд╛ рд╣реИ рдФрд░ on_recv()
O рд░рд┐рдПрдХреНрдЯрд░ рдореЗрдВ on_recv()
рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд╕рд╛рде рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд░рддрд╛ рд╣реИред
On_accept () рдлрд╝рдВрдХреНрд╢рди рджрд┐рдЦрд╛рдПрдВ static void on_accept(void *arg, int fd, uint32_t events) { int incoming_conn; SAFE_CALL((incoming_conn = accept(fd, NULL, NULL)), -1); set_nonblocking(incoming_conn); SAFE_CALL(reactor_register(reactor, incoming_conn, EPOLLIN, on_recv, request_buffer_new()), -1); }
OS рдХреЛ EPOLLIN
рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж on_recv()
рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ on_accept()
рджреНрд╡рд╛рд░рд╛ рдкрдВрдЬреАрдХреГрдд рдХрдиреЗрдХреНрд╢рди рдбреЗрдЯрд╛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИред
on_recv()
рдкреВрд░реНрдг HTTP рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рддрдХ рдХрдиреЗрдХреНрд╢рди рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝рддрд╛ рд╣реИ, рдлрд┐рд░ рд╡рд╣ HTTP рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП on_send()
рд╣реИрдВрдбрд▓рд░ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЧреНрд░рд╛рд╣рдХ рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╕реЙрдХреЗрдЯ рдбреЗрд░реЗрдЧрд┐рд╕реНрдЯреНрд╕ рдФрд░ close()
рд╕рд╛рде close()
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
On_recv () рдлрд╝рдВрдХреНрд╢рди рджрд┐рдЦрд╛рдПрдВ static void on_recv(void *arg, int fd, uint32_t events) { RequestBuffer *buffer = arg;
on_send()
рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдм рдУрдПрд╕ рдПрдХ EPOLLOUT
рдШрдЯрдирд╛ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ on_recv()
рджреНрд╡рд╛рд░рд╛ рдкрдВрдЬреАрдХреГрдд рдХрдиреЗрдХреНрд╢рди рдбреЗрдЯрд╛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЫрд╡рд┐ рдХреЗ рд╕рд╛рде рдПрдЪрдЯреАрдПрдордПрд▓ рдпреБрдХреНрдд рдПрдХ HTTP рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рднреЗрдЬрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЗрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЛ on_recv()
ред
On_send () рдлрд╝рдВрдХреНрд╢рди рджрд┐рдЦрд╛рдПрдВ static void on_send(void *arg, int fd, uint32_t events) { const char *content = "<img " "src=\"https://habrastorage.org/webt/oh/wl/23/" "ohwl23va3b-dioerobq_mbx4xaw.jpeg\">"; char response[1024]; sprintf(response, "HTTP/1.1 200 OK" CRLF "Content-Length: %zd" CRLF "Content-Type: " "text/html" DOUBLE_CRLF "%s", strlen(content), content); SAFE_CALL(send(fd, response, strlen(response), 0), -1); SAFE_CALL(reactor_reregister(reactor, fd, EPOLLIN, on_recv, arg), -1); }
рдФрд░ рдЕрдВрдд рдореЗрдВ, рдлрд╝рд╛рдЗрд▓ рдореЗрдВ http_server.c
, main()
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рд╣рдо reactor_new()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ I / O рд░рд┐рдПрдХреНрдЯрд░ рдмрдирд╛рддреЗ рд╣реИрдВ, рдПрдХ рд╕рд░реНрд╡рд░ рд╕реЙрдХреЗрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╣реИрдВ, рд░рд┐рдПрдХреНрдЯрд░ рдХреЛ reactor_run()
рдареАрдХ рдПрдХ рдорд┐рдирдЯ рдХреЗ reactor_run()
рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ рдФрд░ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддреЗ рд╣реИрдВ рдХрд╛рд░реНрдпрдХреНрд░рдо рд╕реЗред
Http_server.c рджрд┐рдЦрд╛рдПрдБ #include "reactor.h" static Reactor *reactor; #include "common.h" int main(void) { SAFE_CALL((reactor = reactor_new()), NULL); SAFE_CALL( reactor_register(reactor, new_server(false), EPOLLIN, on_accept, NULL), -1); SAFE_CALL(reactor_run(reactor, SERVER_TIMEOUT_MILLIS), -1); SAFE_CALL(reactor_destroy(reactor), -1); }
рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдЕрдкреЗрдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд╣рдо рд╕рдВрдХрд▓рд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдЯ рдореЗрдВ chmod a+x compile.sh && ./compile.sh
) рдФрд░ рд╕реНрд╡-рд▓рд┐рдЦрд┐рдд рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ http://127.0.0.1:18470 рдЦреЛрд▓реЗрдВ рдФрд░ рдЬреЛ рдЕрдкреЗрдХреНрд╖рд┐рдд рдерд╛ рдЙрд╕рдХрд╛ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░реЗрдВ:

рдкреНрд░рджрд░реНрд╢рди рдорд╛рдк
рдореЗрд░реА рдХрд╛рд░ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рджрд┐рдЦрд╛рдПрдВ $ screenfetch MMMMMMMMMMMMMMMMMMMMMMMMMmds+. OS: Mint 19.1 tessa MMm----::-://////////////oymNMd+` Kernel: x86_64 Linux 4.15.0-20-generic MMd /++ -sNMd: Uptime: 2h 34m MMNso/` dMM `.::-. .-::.` .hMN: Packages: 2217 ddddMMh dMM :hNMNMNhNMNMNh: `NMm Shell: bash 4.4.20 NMm dMM .NMN/-+MMM+-/NMN` dMM Resolution: 1920x1080 NMm dMM -MMm `MMM dMM. dMM DE: Cinnamon 4.0.10 NMm dMM -MMm `MMM dMM. dMM WM: Muffin NMm dMM .mmd `mmm yMM. dMM WM Theme: Mint-Y-Dark (Mint-Y) NMm dMM` ..` ... ydm. dMM GTK Theme: Mint-Y [GTK2/3] hMM- +MMd/-------...-:sdds dMM Icon Theme: Mint-Y -NMm- :hNMNNNmdddddddddy/` dMM Font: Noto Sans 9 -dMNs-``-::::-------.`` dMM CPU: Intel Core i7-6700 @ 8x 4GHz [52.0┬░C] `/dMNmy+/:-------------:/yMMM GPU: NV136 ./ydNMMMMMMMMMMMMMMMMMMMMM RAM: 2544MiB / 7926MiB \.MMMMMMMMMMMMMMMMMMM
рд╣рдо рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╕рд░реНрд╡рд░ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдорд╛рдкрддреЗ рд╣реИрдВред рдЖрдЗрдП рджреЛ рдЯрд░реНрдорд┐рдирд▓ рдЦреЛрд▓реЗрдВ: рдПрдХ рдореЗрдВ рд╣рдо рдЪрд▓рд╛рддреЗ рд╣реИрдВ ./http_server
, рджреВрд╕рд░реЗ рдореЗрдВ - wrk ред рдПрдХ рдорд┐рдирдЯ рдХреЗ рдмрд╛рдж, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЖрдВрдХрдбрд╝реЗ рджреВрд╕рд░реЗ рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрдВрдЧреЗ:
$ wrk -c100 -d1m -t8 http://127.0.0.1:18470 -H "Host: 127.0.0.1:18470" -H "Accept-Language: en-US,en;q=0.5" -H "Connection: keep-alive" Running 1m test @ http://127.0.0.1:18470 8 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 493.52us 76.70us 17.31ms 89.57% Req/Sec 24.37k 1.81k 29.34k 68.13% 11657769 requests in 1.00m, 1.60GB read Requests/sec: 193974.70 Transfer/sec: 27.19MB
рд╣рдорд╛рд░рд╛ рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐ рдорд┐рдирдЯ 11 рдорд┐рд▓рд┐рдпрди рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛, рдЬреЛ 100 рдХрдиреЗрдХреНрд╢рди рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реБрдЖ рдерд╛ред рдПрдХ рдмреБрд░рд╛ рдкрд░рд┐рдгрд╛рдо рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдЗрд╕рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?
рдмрд╣реБрд╕реНрддрд░реАрдп рд╕рд░реНрд╡рд░
рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдПрдХ I / O рд░рд┐рдПрдХреНрдЯрд░ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдзрд╛рд░рд╛рдУрдВ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рд╕рднреА CPU рдХреЛрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЖрдЗрдП рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░реЗрдВ:
Http_server_multithreaded.c рджрд┐рдЦрд╛рдПрдБ #include "reactor.h" static Reactor *reactor; #pragma omp threadprivate(reactor) #include "common.h" int main(void) { #pragma omp parallel { SAFE_CALL((reactor = reactor_new()), NULL); SAFE_CALL(reactor_register(reactor, new_server(true), EPOLLIN, on_accept, NULL), -1); SAFE_CALL(reactor_run(reactor, SERVER_TIMEOUT_MILLIS), -1); SAFE_CALL(reactor_destroy(reactor), -1); } }
рдЕрдм рдкреНрд░рддреНрдпреЗрдХ рдзрд╛рдЧрд╛ рдХрд╛ рдЕрдкрдирд╛ рд░рд┐рдПрдХреНрдЯрд░ рд╣реИ:
static Reactor *reactor; #pragma omp threadprivate(reactor)
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ new_server()
рдХрд╛ рддрд░реНрдХ true
ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рд╕рд░реНрд╡рд░ рд╕реЙрдХреЗрдЯ рдХреЛ SO_REUSEPORT
рд╡рд┐рдХрд▓реНрдк рдореЗрдВ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реЗрдЯ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЖрдк рдпрд╣рд╛рдВ рдФрд░ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред
рджреВрд╕рд░рд╛ рд░рди
рдЕрдм рд╣рдо рдПрдХ рдмрд╣реБрд╕реНрддрд░реАрдп рд╕рд░реНрд╡рд░ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдорд╛рдкреЗрдВрдЧреЗ:
$ wrk -c100 -d1m -t8 http://127.0.0.1:18470 -H "Host: 127.0.0.1:18470" -H "Accept-Language: en-US,en;q=0.5" -H "Connection: keep-alive" Running 1m test @ http://127.0.0.1:18470 8 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 1.14ms 2.53ms 40.73ms 89.98% Req/Sec 79.98k 18.07k 154.64k 78.65% 38208400 requests in 1.00m, 5.23GB read Requests/sec: 635876.41 Transfer/sec: 89.14MB
1 рдорд┐рдирдЯ рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ ~ 3.28 рдЧреБрдирд╛ рдмрдврд╝ рдЧрдИ! рд▓реЗрдХрд┐рди рдЧреЛрд▓ рд╕рдВрдЦреНрдпрд╛ рддрдХ, рдХреЗрд╡рд▓ ~ рджреЛ рдорд┐рд▓рд┐рдпрди рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рдерд╛, рдЪрд▓реЛ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, perf рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рдЖрдБрдХрдбрд╝реЛрдВ рдХреЛ рджреЗрдЦреЗрдВ:
$ sudo perf stat -B -e task-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,branches,branch-misses,cache-misses ./http_server_multithreaded Performance counter stats for './http_server_multithreaded': 242446,314933 task-clock (msec) # 4,000 CPUs utilized 1 813 074 context-switches # 0,007 M/sec 4 689 cpu-migrations # 0,019 K/sec 254 page-faults # 0,001 K/sec 895 324 830 170 cycles # 3,693 GHz 621 378 066 808 instructions # 0,69 insn per cycle 119 926 709 370 branches # 494,653 M/sec 3 227 095 669 branch-misses # 2,69% of all branches 808 664 cache-misses 60,604330670 seconds time elapsed
рд╕реАрдкреАрдпреВ рдЖрддреНрдореАрдпрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ , -march=native
, -march=native
рд╕рд╛рде рд╕рдВрдХрд▓рд┐рдд рдХрд░рдирд╛, рдХреИрд╢ рдореЗрдВ рд╣рд┐рдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ MAX_EVENTS
рдФрд░ EPOLLET
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╡реГрджреНрдзрд┐ рдирд╣реАрдВ рд╣реБрдИред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рдЖрдк рдПрдХ рд╕рд╛рде рдХрдиреЗрдХреНрд╢рди рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ?
352 рдПрдХ рд╕рд╛рде рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдЖрдБрдХрдбрд╝реЗ:
$ wrk -c352 -d1m -t8 http://127.0.0.1:18470 -H "Host: 127.0.0.1:18470" -H "Accept-Language: en-US,en;q=0.5" -H "Connection: keep-alive" Running 1m test @ http://127.0.0.1:18470 8 threads and 352 connections Thread Stats Avg Stdev Max +/- Stdev Latency 2.12ms 3.79ms 68.23ms 87.49% Req/Sec 83.78k 12.69k 169.81k 83.59% 40006142 requests in 1.00m, 5.48GB read Requests/sec: 665789.26 Transfer/sec: 93.34MB
рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрдиреЗрдХреНрд╢рди рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ 1 рдорд┐рдирдЯ рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рджрд┐рдЦрд╛рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рдЧреНрд░рд╛рдл:

рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╕реИрдХрдбрд╝реЛрдВ рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдХреЗ рдмрд╛рдж, рджреЛрдиреЛрдВ рд╕рд░реНрд╡рд░реЛрдВ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рддреЗрдЬреА рд╕реЗ рдЧрд┐рд░рддреА рд╣реИ (рдПрдХ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рдпрд╣ рдЕрдзрд┐рдХ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ)ред рдХреНрдпрд╛ рдпрд╣ рд▓рд┐рдирдХреНрд╕ рдЯреАрд╕реАрдкреА / рдЖрдИрдкреА рд╕реНрдЯреИрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ? рдЗрд╕ рддрд░рд╣ рдХреЗ рдЧреНрд░рд╛рдл рд╡реНрдпрд╡рд╣рд╛рд░ рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдмрд╣реБрд╕реНрддрд░реАрдп рдФрд░ рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рдЕрдиреБрдХреВрд▓рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдкрдиреА рдорд╛рдиреНрдпрддрд╛рдУрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред
рдЬреИрд╕рд╛ рдХрд┐ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдпрд╣ рдкреНрд░рджрд░реНрд╢рди рдкрд░реАрдХреНрд╖рдг рд╡рд╛рд╕реНрддрд╡рд┐рдХ рднрд╛рд░ рдкрд░ рдЖрдИ / рдУ рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдирд╣реАрдВ рджрд┐рдЦрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рд╕рд░реНрд╡рд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рддрд╛ рд╣реИ, рд▓реЙрдЧ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЯреАрдПрд▓рдПрд╕ рдХреЗ рд╕рд╛рде рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЖрджрд┐, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд▓реЛрдб рд╡рд┐рд╖рдо (рдЧрддрд┐рд╢реАрд▓) рд╣реИред рддреГрддреАрдп-рдкрдХреНрд╖ рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг I / O рдкреНрд░реЛрдХреНрдЯрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд▓реЗрдЦ рдореЗрдВ рдЖрдпреЛрдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдЖрдИ / рдУ рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рдиреБрдХрд╕рд╛рди
рдЖрдкрдХреЛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ I / O рд░рд┐рдПрдХреНрдЯрд░ рдХрдорд┐рдпрд╛рдВ рдХреЗ рдмрд┐рдирд╛ рдирд╣реАрдВ рд╣реИ, рдЕрд░реНрдерд╛рддреН:
- рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ I / O рд░рд┐рдПрдХреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдХреБрдЫ рдЕрдзрд┐рдХ рдХрдард┐рди рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдкреНрд░рд╡рд╛рд╣ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
- рдЕрднреНрдпрд╛рд╕ рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рднрд╛рд░ рд╡рд┐рд╖рдо рд╣реИ, рдЬреЛ рдЗрд╕ рддрдереНрдп рдХреЛ рдЬрдиреНрдо рджреЗ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдзрд╛рдЧрд╛ рдиреАрдЪреЗ рд░рдЦрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдмрдХрд┐ рджреВрд╕рд░рд╛ рдХрд╛рдо рд╕реЗ рднрд░рд╛ рд╣реБрдЖ рд╣реИред
- рдпрджрд┐ рдХреЛрдИ рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рд╕реНрдЯреНрд░реАрдо рдХреЛ рдмреНрд▓реЙрдХ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╕рд┐рд╕реНрдЯрдо рд╕рд┐рд▓реЗрдХреНрдЯрд░ рдЦреБрдж рднреА рдмреНрд▓реЙрдХ рд╣реЛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рд╕реЗ рд╣рд╛рд░реНрдб-рдЯреВ-рдХреИрдЪ рдмрдЧ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред
рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ I / O рдкреНрд░реЙрдХреНрдЯрд░ рджреНрд╡рд╛рд░рд╛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдХреНрд╕рд░ рдПрдХ рдЕрдиреБрд╕реВрдЪрдХ рдХреЗ рд╕рд╛рде рдЬреЛ рд╕рдорд╛рди рд░реВрдк рд╕реЗ рдереНрд░реЗрдб рдкреВрд▓ рдХреЛ рд▓реЛрдб рд╡рд┐рддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдореЗрдВ рдПрдХ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдПрдкреАрдЖрдИ рднреА рд╣реИред рдЗрд╕рдХреА рдЪрд░реНрдЪрд╛ рдмрд╛рдж рдореЗрдВ рдореЗрд░реЗ рджреВрд╕рд░реЗ рд▓реЗрдЦ рдореЗрдВ рдХреА рдЬрд╛рдПрдЧреАред
рдирд┐рд╖реНрдХрд░реНрд╖
рдЗрд╕ рдкрд░, рдереНрдпреЛрд░реА рдкреНрд░реЛрдлрд╛рдЗрд▓рд░ рдореЗрдВ рд╕реАрдзреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рд╕реЗ рд╣рдорд╛рд░реА рдпрд╛рддреНрд░рд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдИред
рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рди рджреЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рдиреЗрдЯрд╡рд░реНрдХ рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдХреЛ рд╕реБрд╡рд┐рдзрд╛ рдФрд░ рдЧрддрд┐ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╕реНрддрд░реЛрдВ рдХреЗ рд╕рд╛рде рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдЕрдиреНрдп рд╕рдорд╛рди рд░реВрдк рд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИрдВред рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рд▓рд┐рдВрдХ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рд╣реИрдВред
рдЬрд▓реНрдж рдорд┐рд▓рддреЗ рд╣реИрдВ!
рджрд┐рд▓рдЪрд╕реНрдк рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ
рдФрд░ рдХреНрдпрд╛ рдкрдврд╝рдирд╛ рд╣реИ?