تولد یک سیستمعامل، بخش هفتم
آری لمکه باید آدم خوشبینی بوده باشد. او مدتها پیش از اینکه من چیزی برای ارائه داشته باشم، مسیر اف.تی.پی. ftp.funer.fi را ساخت. من کلمه رمز را داشتم و همه چیز تنظیم شده بود تا در موقع مناسب به سیستم وارد شوم و فایلها را در آنجا آپلود کنم. حدود چهار ماه طول کشید تا احساس کنم چیزی دارم که میتوان آن را با جهانیان به اشتراک گذاشت یا حداقل با آری و چند خوره سیستمعامل دیگری که گاهگداری با آنها ایمیل رد و بدل میکردم.
هدف اصلی من ایجاد سیستمعاملی بود که در نهایت بتوانم از آن به عنوان جایگزین مینیکس استفاده کنم. قرار نبود کاری بیشتر از مینیکس انجام دهم. برنامه اولیه این بود که چیزهایی که در مینیکس دوست دارم را تکرار کنم و همینطور چند قابلیت دیگر را. برای مثال نه تنها شبیهساز ترمینال مینیکس بد بود که کنترل وظیفه هم نداشت؛ یعنی نمیشد در حینی که نیازی به یک برنامه نداشتیم، آن را به پشت زمینه منتقل کنیم. مدیریت حافظه مینیکس هم خیلی ابتدایی بود و در سیستمعامل مک هنوز هم همینطور است.
روش نوشتن یک سیستمعامل این است که اول کشف کنید فراخوانیهای سیستمی قرار است چهکاری انجام دهند و بعد برنامههایی بنویسید که این وظایف را به شیوهای که شما دوست دارید، عملیاتی کنند. به شکل عمومی، چیزی حدود چند صد فراخوانی سیستمی وجود دارد که بعضی از آنها نیازمند چند تابع گوناگون هستند. البته بعضیها هم سادهاند. بعضی از فراخوانیهای پایهای بسیار پیچیده هستند و پیادهسازی آنها نیازمند کلی کار زیربنایی است؛ مثلا فراخوانیهای سیستمی «خواندن» یا «نوشتن» را در نظر بگیرید. برای خواندن یا نوشتن از دیسک، نیازمند این هستید که قبلا یک درایور دیسک نوشته باشید. حالا «باز کردن» را در نظر بگیرید. باید کل لایه فایل سیستم را بسازید تا یک تابع بتواند اسم فایلی را بگیرد و آن را باز کند. نوشتن «باز کردن» شاید چند ماه کار برد ولی وقتی عملیاتی شد، از همان کد میشد در قسمتهای دیگر هم استفاده کرد.
این روش توسعه اولیه بود. من از راهنماهای سان یا کتابهای دیگر، استانداردها را میخواندم و یکییکی فراخوانیهای سیستمی را انتخاب میکردم و سعی میکردم توابعی بنویسم که آنها را عملیاتی کنند. کار سخت و طاقتفرسایی بود.
دلیل: هیچچیزی اتفاق نمیافتاد، هیچ پیشرفتی را عملا مشاهده نمیکردید. میتوانستید برنامههای کوچکی بنویسید که کد تازه نوشته شده را آزمایش کنند ولی عملا چیزی کاربردی از این کدها بیرون نمیآمد. بعد از مدتی، دیگر روند انتخاب تکتک فراخوانیها از یک فهرست بلندبالا را کنار میگذاشتید و احساس میکردید که فراخوانیها آن قدر کامل شدهاند که بتوانید برنامههای واقعی را روی آنها اجرا کنید. اولین برنامهای که باید اجرا کنید، پوسته است چون اجرای دیگر برنامهها بدون حضور پوسته، بسیار مشکل است. علاوه بر این، پوسته شامل بسیاری از فراخوانیهای سیستمیای است که دیگر برنامهها هم از آنها استفاده خواهند کرد. پوسته را اجرا کنید و فهرستی از فراخوانیهایی را خواهید داشت که باید یکبهیک بنویسیدشان.
در یونیکس، پوسته به نوعی مادر همه برنامههای دیگر است. پوسته آنجاست تا برنامههای اجرایی دیگر را اجرا کند (برنامه اجرایی، فایلی است که به شکل ۰ و ۱ به ماشین میگوید که چهکار کند. هربار که برنامهای را به یک زبان برنامهنویسی مینویسید، باید آن را از کد منبع به باینری ترجمه کنید). در عین حال این پوسته است که به شما اجازه میدهد وارد سیستم شوید. قبول! در یونیکس اولین برنامهای که به شکل سنتی اجرا میشود init نام دارد ولی اجرای init به حجم زیادی از زیرساخت نیاز دارد و کنترلکننده کل اتفاقاتی است که روی میدهند. وقتی چیزی برای اجرا شدن نیست، داشتن init هم لزومی ندارد.
پس به جای شروع به اجرای init، اولین کاری که کرنل من میکرد، اجرای پوسته بود. من حدود بیست و پنج فراخوانی سیستمی را نوشته بودم و همان طور که گفتم، این اولین برنامه واقعی بود که میخواستم اجرا کنم. پوسته چیزی نبود که من آن را نوشته باشم. من یکی از پوستههای اصلی یونیکس که یکی از مشابههای پوستهای به نام پوسته بورن را دانلود کرده و روی دیسک ریخته بودم. این پوسته به عنوان یک نرمافزار روی اینترنت در دسترس همه بود و اسمش را از یک شوخی ناجور گرفته بود. کسی که پوسته اصلی را نوشته بود Bourne نام داشت و در نتیجه این مشابه، Bourne-Again یا به اختصار bash نام گرفته بود.
وقتی سعی میکنید یک برنامه واقعی را از دیسک بارگذاری کنید، بدون شک با یک باگ در درایور دیسک یا برنامه بارگذار مواجه خواهید شد. از آنجایی که برنامه بارگذار نمیفهمد مشغول چهکاری است، همیشه فهرستی از کارهای در حال اقدام را چاپ میکند. این بسیار مهم است؛ چون با این روش دقیقا میفهمید که اشکال در کجا بروز کرده است.
من در مرحلهای بودم که برنامهام پوسته را از دیسک بارگذاری میکرد و هر فراخوانی سیستمی که صدا زده میشد؛ ولی من هنوز آن را ننوشته بودم را چاپ میکرد. من کامپیوتر را بوت کردم؛ پوسته را اجرا کردم و چیزی شبیه به این ظاهر شد: «فراخوانی سیستمی شماره ۵۱۲ نوشته نشده است.» من صبح و شب به این نوشتهها نگاه میکردم و فراخوانیهای جدید ر ا مینوشتم و قبلیها را اصلاح میکردم. اینکار بسیار لذتبخشتر بود از اینکه فهرستی از فراخوانیها را جلویم بگذارم و یکییکی آنها را بنویسم. با این کار، پیشرفت را میدیدم.
اواخر آگوست یا اوایل سپتامبر بود که توانستم پوسته را به طور کامل اجرا کنم. از آن به بعد، همه چیز آسانتر شد.
این مساله بزرگی بود.
وقتی پوسته را راهانداختم، توانستم سریعا چند برنامه را کمپایل کنم. برای مثال پوسته خیلی خیلی پیچیدهتر از برنامهای مثل cp (کپی) یا I (برای گرفتن فهرست فایلها) بود. هر چیزی که لازم داشتم، بخشی از پوسته بود که قبلا نوشته شده بود و در نتیجه وقتی پوسته راه افتاد، از کمی بالای صفر تا ۱۰۰، در مدت خیلی کمی پیموده شد. گاهی آن قدر همه چیز آماده بود که من احساس کنفیکون میکردم. قبل از این، هیچچیز کار نمیکرد.
بله! احساس رضایت فوقالعادهای داشتم. فکر میکنم این مهم بود چون آن تابستان به جز کامپیوتر، هیچ کار دیگری نکرده بودم. اغراق نمیکنم. از آوریل تا آگوست، بهترین ایام سال در فنلاند است. مردم برای قایقسواری به مجمعالجزایر میروند و در سواحل آفتاب میگیرند و در سوناهای تابستانیشان وقت میگذرانند؛ اما من به سختی میتوانستم بگویم شب است یا روز و حتی چه موقعی از سال است. آن پردههای سیاه و کلفت جلوی نور آفتاب تقریبا بیستوچهار ساعته را میگرفتند، همین طور جلوی دنیای بیرون را. بعضی روزها -یا شبها؟ از تخت بیرون میآمدم و مستقیما به سراغ کامپیوترم که کمتر از نیم متر با تخت فاصله داشت میرفتم. در نهایت پدرم شروع کرد تا در این باره که چرا من یک شغل تابستانی نمیگیرم، به مادرم غر بزند. مساله برای مادرم مهم نبود: من او را اذیت نمیکردم. سارا از اینکه وقتی من آنلاین میشدم، خطوط تلفن مدتها مشغول میشد، کمی ناراضی بود. احتمالا خودش این جمله را با مراعات کمتری مینوشت. اغراق نخواهد بود اگر بگویم که به جز از طریق کامپیوتر، هیچ ارتباطی با دنیای خارج نداشتم. باشه! شاید هفتهای یکبار دوستی میآمد و به پنجره تقهای میزد و اگر من مشغول بالا و پایین رفتن در بخش مهمی از کد نبودم، به داخل دعوتش میکردم (توجه کنید که مهمان همیشه مرد بود. این قبل از دورانی بود که گیک بودن باحال محسوب شود). ما چای مینوشیدیم و در آشپزخانه کوچکمان، یک ساعتی ام.تی.وی. نگاه میکردیم. حالا که درست فکر میکنم، میبینم که گاهی اگر کسی مثل جوکو (که من او را آوونتون صدا میزنم که به معنای «قاتل اژدها» است و این خودش داستانی دارد) به پنجره تقه میزد، ممکن بود با هم بیرون برویم و آبجویی بخوریم و کمی اسنوکر بازی کنیم؛ اما صادقانه بگویم که در آن دوران هیچچیز دیگری در زندگی من وجود نداشت.
این را هم بگویم که طی آن دوره به هیچ وجه یک آدم بیچاره رنگپریده نبودم. پوسته، کار میکرد و این به آن معنا بود که من پایههای یک سیستمعامل را نوشتهام. این کار مفرح بود.
با عملیاتی شدن پوسته، شروع کردم به آزمایش برنامههای درونساخت آن. بعد آن قدر برنامه جدید کمپایل کردم که بتوانم واقعا کار مفیدی انجام دهم. همه چیز را در مینیکس کمپایل میکردم و یک پارتیشن هارد را هم اختصاص داده بودم به سیستمعامل جدید و پوسته را هم به آن انتقال داده بودم. پیش خودم آن را لینوکس میخواندم.
صادقانه: هیچگاه نمیخواستم برنامه را با نام لینوکس منتشر کنم چون این کار به نظرم خودخواهانه میآمد. پس اسمی که در نظر گرفته بودم چه بود؟ فریکس (گرفتید؟ Freaks با پسوند مشهور x). در حقیقت بعضی از فایلهای ساخت اولیه -فایلهایی که مشخص میکنند فایل منبع چگونه باید کمپایل شود- برای تقریبا نیم سال، عبارت فریکس را در خود داشتند. البته این مساله ارزشی هم نداشت چون در آن مرحله اصولا برنامهای برای انتشار عمومی این نرمافزار نداشتم.