فرآیند os/process
اجرای برنامههای دیگر، گرفتن خروجیشان، صبر برای پایانشان و متوقف کردنشان.
واردسازی سیستم عامل.فرآیند
بستهی فرآیند یک برنامهی دیگر را مستقیم، بدون پوسته، اجرا میکند. مسیر برنامه و آرگومانها جدا داده میشوند، پس نیازی به نقلقولگذاری نیست و فاصلهها یا نویسههای خاص در آرگومانها مشکلی درست نمیکنند. با آن ابزارهایی مثل git، ffmpeg یا یک کامپایلر را با نام پروندههایی که از کاربر آمده صدا بزنید. برای یک فرمان یکخطی پوسته بستهی سیستم عامل (اجرا، اجرا با خروجی) یا پوسته را ببینید؛ وقتی برنامهای اصلاً اجرا نمیشود، دلیلش در خطا ثبت میشود.
هر اجرا حداکثر چهار گام دارد: شروع یا شروع با ضبط برنامه را راه میاندازد و بیدرنگ برمیگردد، انتظار تا پایان برنامه منتظر میماند و کد خروج را برمیگرداند، خواندن خروجی و خواندن خطا آنچه را اجرای ضبطشده چاپ کرده میخوانند، و پاکسازی دو پروندهی موقتی را که آن را نگه داشتهاند پاک میکند. برنامهی ضبطشده ورودی استاندارد خالی میگیرد.
اشتباههای رایج:
- بررسی زنده دانستن
در حال اجرا. این تابع پرچمی را گزارش میکند کهشروعروشنش میکند و فقطانتظار،کشتنیاپایان دادنخاموشش میکنند؛ پس از اینکه برنامه خودش تمام شد هم درست میماند. - کشتن بدون انتظار.
کشتنوپایان دادنفقط علامت را میفرستند. پس از آنهاانتظاررا صدا بزنید، وگرنه فرآیندِ تمامشده به شکل زامبی در جدول فرآیندها میماند. - انتظار مهلت زمانی.
انتظارتا هر وقت برنامه کار کند صبر میکند. برای کنار کشیدن پس از مدتی، در یک نخ منتظر بمانید و از نخ اصلیکشتنرا صدا بزنید. - فراموش کردن
پاکسازی. هر اجرای ضبطشده تا صدا زدن آن دو پرونده در پوشهی موقت میگذارد.
در ویندوز آرگومانها به یک خط فرمان پیوسته میشوند و فقط آنهایی که فاصله دارند در نقلقول میروند، و برنامه با CreateProcessA (نسخهی ANSI) اجرا میشود. آرگومانی که خودش " دارد، یا متنی بیرون از صفحهکد سیستم مثل فارسی، آنجا سالم نمیرسد؛ انشعاب و انتظار شناسه هم -۱ برمیگردانند.
رساندن آرگومانها همانطور که هستند
هر عضو وکتور آرگومانها، بایت به بایت، یک آرگومان برای برنامه میشود. فاصله، نقلقول، $ یا ; معنای خاصی ندارند، چون هیچ پوستهای آنها را نمیخواند. برای همین این بسته راه امن رساندن نام پروندهها و هر متنی است که از کاربر آمده.
واردسازی سیستم عامل.فرآیند
تابع ریشه:
ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
دیرکن آرگ.آزادکن()
آرگ.بیفزا("[%s]\n")
آرگ.بیفزا("دو واژه")
آرگ.بیفزا("it's quoted")
آرگ.بیفزا("$HOME")
آرگ.بیفزا("*.txt; rm -rf x")
ناپایا ف := فرآیند.شروع با ضبط("printf"، آرگ)
فرآیند.انتظار(ف)
چاپ فرآیند.خواندن خروجی(ف)
فرآیند.پاکسازی(ف)
پایاننام برنامه مثل پایانه در PATH جستجو میشود، پس printf بدون مسیر کامل هم کار میکند. خود نام برنامه در وکتور نمیآید؛ بسته آن را میافزاید. این دقت در لینوکس و مک برقرار است؛ برای ویندوز یادداشت بالا را ببینید.
کد خروج، خروجی و خروجی خطا
برنامه موفقیت را با کد خروج صفر و شکست را با هر عدد دیگری اعلام میکند و گلههایش را در خروجی خطا مینویسد. پس از انتظار هر دو را بخوانید: خواندن خروجی برای نتیجه و خواندن خطا برای علت شکست. بعد از خواندن پاکسازی را صدا بزنید، چون خروجی ضبطشده تا آن موقع در پروندههای موقت میماند.
واردسازی سیستم عامل.فرآیند
تابع ریشه:
ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
دیرکن آرگ.آزادکن()
آرگ.بیفزا("-c")
آرگ.بیفزا("echo در حال رونوشت; echo دیسک پر است >&2; exit 3")
ناپایا ف := فرآیند.شروع با ضبط("sh"، آرگ)
کد := فرآیند.انتظار(ف)
خروجی := فرآیند.خواندن خروجی(ف).پیراست()
پیام خطا := فرآیند.خواندن خطا(ف).پیراست()
فرآیند.پاکسازی(ف)
سرچاپ "خروجی:"، خروجی
اگر کد != ۰:
سرچاپ "با کد"، کد، "شکست خورد و گفت:"، پیام خطا
برگشت ۰
پایان
سرچاپ "همه چیز درست بود"
پایاناجرای چند برنامه با هم
شروع با ضبط همین که برنامه راه افتاد برمیگردد، پس میتوانید چند برنامه را شروع کنید و بعد برای همه صبر کنید. زمان کل نزدیک به زمان کندترینشان است، نه جمع همه. اگر به همان ترتیبی که شروع کردهاید صبر کنید، ترتیب خروجی ثابت میماند، حتی اگر کاری که دیرتر شروع شده زودتر تمام شود.
واردسازی سیستم عامل.فرآیند
تابع کار(نام: رشته، ثانیه: رشته): فرآیند.فرآیند:
ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
دیرکن آرگ.آزادکن()
آرگ.بیفزا("-c")
آرگ.بیفزا("sleep " + ثانیه + "; echo " + نام + " تمام شد")
برگشت فرآیند.شروع با ضبط("sh"، آرگ)
پایان
تابع ریشه:
ناپایا کارها := وکتور {} برگردان وکتور<فرآیند.فرآیند>
دیرکن کارها.آزادکن()
کارها.بیفزا(کار("تصویرکها"، "0.3"))
کارها.بیفزا(کار("نمایهی جستجو"، "0.1"))
کارها.بیفزا(کار("نقشهی سایت"، "0.2"))
سرچاپ کارها.طول()، "کار شروع شد"
تکرار کارها.طول() در ش:
ناپایا ف := کارها.بگیر(ش)
کد := فرآیند.انتظار(ف)
سرچاپ کد، فرآیند.خواندن خروجی(ف).پیراست()
فرآیند.پاکسازی(ف)
پایان
پایانتعداد برنامههای همزمان را معقول نگه دارید؛ برای کارهایی که پردازنده را درگیر میکنند، تعداد پردازنده از بستهی سکو سقف خوبی است.
تابع کمکیای که برنامه را اجرا میکند و خروجی را برمیگرداند
بیشتر برنامهها هر بار همان چند سطر را لازم دارند: شروع، بررسی اینکه راه افتاد، انتظار، خواندن و پاکسازی. آنها را در یک تابع بگذارید. یک دیرکن درست پس از شروع مطمئن میشود پاکسازی از هر راهی که تابع تمام شود اجرا شود، و یک پارامتر خروجی به فراخواننده میگوید برنامه موفق بوده یا نه.
واردسازی سیستم عامل.خطا
واردسازی سیستم عامل.فرآیند
تابع ضبط(برنامه: رشته، آرگ: وکتور<رشته>، موفق &: منطقی): رشته:
خطا.پاک کردن خطا()
ناپایا ف := فرآیند.شروع با ضبط(برنامه، آرگ)
اگر خطا.خطا دارد():
موفق = نادرست
برگشت ""
پایان
دیرکن فرآیند.پاکسازی(ف)
موفق = فرآیند.انتظار(ف) == ۰
برگشت فرآیند.خواندن خروجی(ف)
پایان
تابع ریشه:
ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
دیرکن آرگ.آزادکن()
آرگ.بیفزا("-c")
آرگ.بیفزا("printf '۳۰\\n۱۰\\n۲۰\\n' | sort")
ناپایا موفق := نادرست
خروجی := ضبط("sh"، آرگ، موفق)
سرچاپ "موفق بود:"، موفق
چاپ خروجی
ضبط("/no/such/tool"، آرگ، موفق)
سرچاپ "ابزار ناموجود موفق بود:"، موفق
پایانمتوقف کردن یک برنامه
پایان دادن علامت SIGTERM را میفرستد که برنامهی درسترفتار آن را میگیرد تا کارش را ذخیره کند و بیرون برود؛ کشتن علامت SIGKILL را میفرستد که گرفتنی نیست. در هر دو حالت، پس از آن انتظار برنامه را جمع میکند. برنامهای که با علامت تمام شده، ۱۲۸ بهعلاوهی شمارهی علامت را بهعنوان کد خروج گزارش میکند؛ پس ۱۴۳ یعنی SIGTERM و ۱۳۷ یعنی SIGKILL، همان عددهایی که پوسته نشان میدهد.
واردسازی سیستم عامل.فرآیند
تابع ریشه:
ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
دیرکن آرگ.آزادکن()
آرگ.بیفزا("30")
ناپایا کارگر := فرآیند.شروع("sleep"، آرگ)
سرچاپ "شروع شد، در حال اجرا:"، فرآیند.در حال اجرا(کارگر)
اگر فرآیند.پایان دادن(کارگر) != ۰:
سرچاپ "نتوانستم به آن علامت بفرستم"
برگشت ۱
پایان
کد := فرآیند.انتظار(کارگر)
سرچاپ "با کد خروج"، کد، "متوقف شد = 128 + علامت"، کد - ۱۲۸
سرچاپ "در حال اجرا:"، فرآیند.در حال اجرا(کارگر)
برگشت ۰
پایان| نیاز | چه به کار ببرید |
|---|---|
| اجرای برنامه و دیدن خروجیاش روی صفحه | شروع، سپس انتظار |
| اجرای برنامه و استفاده از خروجیاش | شروع با ضبط، انتظار، خواندن خروجی، پاکسازی |
| متوقف کردن مؤدبانه یا فوری | پایان دادن، کشتن |
| لوله یا هدایت خروجی | اجرای sh با -c و یک اسکریپت، مثل نمونههای بالا |
| یک فرمان یکخطی و نتیجهاش | پوسته |
گونهها
فرآیند Process
ساختار فرآیند| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| شناسه | pid | صحیح = 0 | شناسهی فرآیند. |
| دسته | handle | تهی* | دستگیرهی فرآیند در ویندوز. |
| فعال | running | منطقی = نادرست | شروع روشنش میکند و انتظار، کشتن و پایان دادن خاموشش؛ وقتی برنامه خودش تمام شود بهروز نمیشود. |
| کد خروج | exit_code | صحیح = 0 | کد خروج، پس از برگشتن انتظار؛ اگر علامتی برنامه را تمام کرده باشد، ۱۲۸ بهعلاوهی شمارهی علامت. |
| مسیر خروجی | stdout_path | رشته = "" | پروندهی موقتی که خروجی ضبطشده در آن است. |
| مسیر خروجی خطا | stderr_path | رشته = "" | پروندهی موقتی که خروجی خطای ضبطشده در آن است. |
واردسازی سیستم عامل.فرآیند
تابع ریشه:
ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
دیرکن آرگ.آزادکن()
آرگ.بیفزا("سلام از فرآیند فرزند")
ناپایا ف := فرآیند.شروع با ضبط("/bin/echo"، آرگ)
سرچاپ فرآیند.شناسه فرآیند(ف) > ۰
کد := فرآیند.انتظار(ف)
سرچاپ کد، فرآیند.کد خروج(ف)، فرآیند.در حال اجرا(ف)
چاپ فرآیند.خواندن خروجی(ف)
سرچاپ "[" + فرآیند.خواندن خطا(ف) + "]"
فرآیند.پاکسازی(ف)
پایانتابعها
شروع Start
تابع شروع(path: رشته، args: وکتور<رشته>): فرآیندPATH جستجو میشود. اگر اجرا نشود، pid صفر است و خطا مقدار فرآیند ناموفق را نگه میدارد.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
شروع با ضبط StartCaptured
تابع شروع با ضبط(path: رشته، args: وکتور<رشته>): فرآیندشروع، ولی خروجی و خطای برنامه را به دو پروندهی موقت میفرستد تا پس از انتظار بخوانید، و ورودی استاندارد خالی به آن میدهد.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
انتظار شناسه WaitPid
تابع انتظار شناسه(pid: صحیح): صحیحواردسازی سیستم عامل.فرآیند
تابع ریشه:
ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
دیرکن آرگ.آزادکن()
آرگ.بیفزا("30")
ناپایا ف := فرآیند.شروع("/bin/sleep"، آرگ)
سرچاپ فرآیند.در حال اجرا(ف)
فرآیند.پایان دادن(ف)
فرآیند.انتظار(ف)
سرچاپ فرآیند.در حال اجرا(ف)
ناپایا ف۲ := فرآیند.شروع("/bin/sleep"، آرگ)
فرآیند.کشتن(ف۲)
فرآیند.انتظار شناسه(فرآیند.شناسه فرآیند(ف۲))
سرچاپ "هر دو متوقف شدند"
پایانانتظار Wait
تابع انتظار(p &: فرآیند): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
انشعاب Fork
تابع انشعاب(): صحیحواردسازی سیستم عامل.فرآیند
تابع ریشه:
ش := فرآیند.انشعاب()
اگر ش == ۰:
سرچاپ "من فرزندم"
فرآیند.خروج فوری(۰)
پایان
فرآیند.انتظار شناسه(ش)
سرچاپ "فرزند تمام شد"
پایانخروج فوری ExitNow
تابع خروج فوری(code: صحیح)انشعاب.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Fork.salam
کشتن Kill
تابع کشتن(p &: فرآیند): صحیحانتظار را صدا بزنید تا جمعش کند.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Kill.salam
پایان دادن Terminate
تابع پایان دادن(p &: فرآیند): صحیحانتظار را صدا بزنید. در ویندوز همان کشتن است.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Kill.salam
خواندن خروجی ReadStdout
تابع خواندن خروجی(p: فرآیند): رشتهشروع اجرا شده خالی است. متن در نخستین بایت صفر تمام میشود.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
خواندن خطا ReadStderr
تابع خواندن خطا(p: فرآیند): رشتهشروع اجرا شده خالی است.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
پاکسازی Cleanup
تابع پاکسازی(p &: فرآیند)شروع با ضبط یک بار صدایش بزنید.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
کد خروج ExitCode
تابع کد خروج(p: فرآیند): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
شناسه فرآیند Pid
تابع شناسه فرآیند(p: فرآیند): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam
در حال اجرا IsRunning
تابع در حال اجرا(p: فرآیند): منطقیrunning: از شروع تا انتظار، کشتن یا پایان دادن درست است. از سیستم نمیپرسد، پس پس از اینکه برنامه خودش تمام شد هم درست میماند.نمونهی این مورد همراه با موارد بالاتر آمده است: os-process-Start.salam