<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>پست‌های انتشارات مفاهیم سیستم عامل</title>
        <link>https://virgool.io/linux-internals/feed</link>
        <description>آموزش مفاهیم سیستم عامل</description>
        <language>fa</language>
        <pubDate>2026-06-18 03:23:01</pubDate>
        <image>
            <url>https://files.virgool.io/upload/publication/mfxlcdyf72fm/k59vwf.png</url>
            <title>مفاهیم سیستم عامل</title>
            <link>https://virgool.io/linux-internals</link>
        </image>

                    <item>
                <title>دستور make و فایل MakeFile</title>
                <link>https://virgool.io/linux-internals/%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-make-%D9%88-%D9%81%D8%A7%DB%8C%D9%84-makefile-f3d2uuepnqyg</link>
                <description>در لینوکس (و دیگر سیستم عامل های شبه یونیکس) از کامپایلر gcc برای کامپایل کدهای سی استفاده می شود. خروجی یک برنامه دودویی است که می توان آن را اجرا کنیم. اگر شما از IDE هایی مانند CodeBlocks استفاده می کنید، اینها نیز gcc برای کامپایل می گیرند.gcc main.c -o outpu_bin_fileدر کد بالا گزینه o- برای تعیین نام و مسیر فایل دودویی خروجی استفاده می شود که این فایل دودویی اجرایی از تک فایل main.c ساخته می شود. اکنون گمان کنید که برنامه شما بسیار بزرگ است و چندین و چند فایل c.  دارد. در این حالت در صورت تغییر در یک فایل، به طور معمول همه فایل ها باید از نوع کامپایل (Recompile) شوند، حتی آنهایی که تغییری در آنها داده نشده است.اگر یک بسته کد منبع (Source Code Package) را تا کنون کامپایل کرده باشید، دیده اید که سه دستور زیر را به ترتیب اجرا کرده اید. در این میان دستور make  خودکار متوجه می شود که کدام بخش از یک فایل بزرگ نیاز به کامپایل دوباره دارد.configure
make
sudo make installراهنمای دستور make را با دستور man make بخوانید.درون MakeFile  چه چیزهایی استیک MakeFile‌ شامل یک مجموعه ازهدف ها (Targets) و  Dependencie ها و قاعده ها (Rules) است. یک هدف یا Target یک فایلی است که یا ساخته یا بروز رسانی می شود ولی می تواند یک عبارت (Directive) یا یک بر چسب باشد که توسط برنامه (دستور) make  مورد ارجاع قرار می گیرند.یک هدف وابسته به یک مجموعه از فایل های منبع (Source File)، یا Object File یا حتی یک دسته از Target های دیگر است که این وابستگی ها به گونه فهرستی از Dependency تعریف می شوند. قاعده ها یا Rule ها دستوهای هستند که برای ساخت (Build) هدف ها توسط نیازمندی ها نیاز هستند.زمانی که دستور  make یک MakeFile را می خواند، از روی مهرزمانی (Timestamp) متوجه می شود که کدام (فایل های) هدف (Target) باید ساخته (Build) شوند. اگر مهر زمانی تازه تر باشد، دستور make قواعد (دستورهای) متناسب با هدف را اجرا می کند.در شکل زیر یک نمونه از برنامه ای به زبان سی نشان داده شده است که دارای سه فایل کد منبع به نام های type.h (فایل سرآیند که اعلان تابع mysum و برخی از نوع ها یا ثابت ها را شامل می شود)، فایل mysum.c  (که بدنه تعریف تابع mysum را شامل می شود) و فایل t.c  که پیوست فایل سرآیند type.h و فایل سرآیند stdio.h و بدنه تابع main  را شامل می شود.برای کامپایل آن که دارای دو فایل کد سی به نام های mysum.c و  t.c  است دستور زیر را به کار برده ایم که در آن o- نام فایل دودویی خروجی را مشخص می کند که در اینجا آن را myt نامگذاری کرده ایم.gcc -o myt t.c mysum.cشکل زیر یک نمونه از makefile  را نشان می دهد که نام آن را همان نام معمول MakeFile گذاشته ام. در خط نخست نام Target  آمده است که در اینجا Target  ما همان فایل دودویی اجرایی به نام myt  است. پس از این نام علامت :  قرار گفته و سپس با یک فاصله فهرست وابستگی ها آورده شده است.فهرست وابستگی ها همان فایل هایی هستند که برنامه متکی به آنها است که شامل سه فایل type.h و  t.c و mysum.c است. سپس در خط بعدی که حتما باید با یک TAB آغاز شود، Rule  ها نوشته می شوند که در اینجا همان دستور gcc  است.myt: type.h t.c mysum.c                #target: dependency list
        gcc -o myt t.c mysum.c         # rules: line must begin with a TABاکنون اگر پیش از این فایل myt  را به کمک gcc ساخته اید، آن را پاک کنید و دستور زیر را انجام دهید. همانگونه که گفته شد، دستور make در لینوکس (و دیگر شبه یونیکس ها) فایل MakeFile را می خواند. البته هر فایلی makefile تلقی نمی شود و باید الگوی شکل نخست را داشته باشد که ساده ترین آن در سومین شکل بالا نشان داده شده است.make -f MakeFileدر دستور بالا، جلوی گزینه f- نام فایل makefile  می آید که در اینجا من آن را MakeFile گذاشته ام ولی شما می توانید هر نام دیگری مانند mk1 را بگذارید. پس از اجرای دستور بالا، خروجی زیر نشان داده می شود.gcc -o myt t.c mysum.c # rules: line must begin with a TABاین خروجی همان خط دومی است که با TAB آغاز شده بود و به Rule یا در اینجا دستور کامپایل اشاره می کرد. یادآور می شوم که مزیت استفاده از makefile و دستور make در این است که دستور make با بررسی مهر زمانی، تنها آن فایل هایی را دوباره کامپایل می کند که تغییری در آن رخ داده باشد، زیرا در لینوکس زمان آخرین تغییر (Modify Time) نگهداری می شود و اگر تغییری رخ داده باشد این زمان بروز و make  از آن آگاه می شود.اکنون اگر دوباره دستور make MakeFile را اجرا کنید می بینید که پیغام make: ‘myt’ is up to date نشان داده می شود که بدین معنی است که هیچ تغییری در کدهای برنامه انجام نشده است.شبیه سازی تغییر دادن زمان آخرین تغییر (Modify Time)در سسیتم عامل های یونیکسی دستوری به نام touch است که نام فایلی را دریافت می کند و سپس اگر آن فایل وجود نداشته باشد، آن فایل را می سازد و فیلدهای مختلفی مانند Access Time و  Modify Time را برای آن فایل تنظیم می کند.ولی اگر فایل از قبل وجود داشته باشد، پس تنها فیلدهای مد نظر را تغییر می دهد و چون یکی از این فیلدها Modify Time  است، پس از دید دستور make یک تغییر در فایل های کد منبع رخ داده است. در اینجا برای نمونه دستور زیر را انجام دهید.touch type.hبا این کار Modify Time فایل type.h  تغییر کرده، پس در اجرای دوباره دستور make -f MakeFile تنها همین فایل است که از نو کامپایل می شود. توجه کنید باز کردن و تغییر در یک فایل با هر ویرایشگری، نتیجه اش بروز شدن Modify Time است.منبعبرای فراگیری بیشتر می توانید به سایت زیر نگاهی بیاندازیدhttp://sysadmingeeks.irhttps://dataset-academy.comو یا می توانید در کانال تلگرام عضو شوید.https://t.me/datasetacademydotcom</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Sat, 04 Jul 2020 15:17:28 +0430</pubDate>
            </item>
                    <item>
                <title>فرمت های فایل های دودویی اجرا شدنی</title>
                <link>https://virgool.io/linux-internals/%D9%81%D8%B1%D9%85%D8%AA-%D9%87%D8%A7%DB%8C-%D9%81%D8%A7%DB%8C%D9%84-%D9%87%D8%A7%DB%8C-%D8%AF%D9%88%D8%AF%D9%88%DB%8C%DB%8C-%D8%A7%D8%AC%D8%B1%D8%A7-%D8%B4%D8%AF%D9%86%DB%8C-gxmafehuradi</link>
                <description>پس از نوشتن یک برنامه به هر زبانی مانند سی، سی پلاس پلاس، جاوا یا سی شارپ و دیگر زبان ها، کامپایلر می بایست که یک فایل دودویی از روی کد بسازد. این که این فرایند چگونه است، بحثی جدا را می خواهد ولی به هر رو، برآیند کامپایل یک فایل دودویی اجرا شدنی (Executable Binary File) است.Flat Binary Executableیک فایل Flat Binary Executable (یا FBE) یکی از فایل های دودویی اجرا شدنی است که تنها در برگیرنده کد اجرا شدنی (Executable Code) و داده های آغازین (Initialization Data) است. این گونه فایل دودویی اجرایی، برای اجرا شدن به به طور کامل درون حافظه بارگذاری شود. یک نمونه بارز از فایل دودویی اجرای FBE، فایل بوت سیستم عامل است که برای اجرا شدن، باید تماما در حافظه بارگذاری شود. در واقع FBE یک تک قطعه از کدهایی دودویی اجرا شدنی است که برای اجرا شدن به طور کامل درون حافظه بارگذاری می شوند.a.out Executable Fileیک فایل با پسوند out مانند a.out در آغاز دارای یک سرآیند (Header) است و سپس به دنبال آن بخش کد، سپس بخش داده ها و در پایان بخش BSS () است.ELF Executable Fileسرآغاز این فایل یک سرآیند به نام elf-header است که به دنبال یک یا چندین بخش برنامه (Program Section) می آید. در سیستم عامل لینوکس دستوری به نام readelf است که برای نمایش اطلاعاتی درباره یک فایل ELF به کار می رود.گمان کنید که یک فایل دودویی به نام GtkApp1 داریم و می خواهیم درون مایه آن را درباره فرمت ELF بدانیم. برای این کار می توانید دستور زیر را اجرا کنید که همه اطلاعات ELF را نشان می دهد. در شکل زیر می بینید که سرآغاز فایل سرآیند elf-header است.readelf -a GtkApp1فرمت ELF می تواند تا چندین بخش سرآیند برنامه (Program Header) داشته باشد که این امکان پذیر است که هر یک از این بخش ها درون یک فضای آدرس حافظه اصلی بارگذاری شوند. این فرمت فایل دودویی اجرای پیش فرض در سیستم عامل لینوکس است که برای پیوند پویا (Dynamic Linking) کارآتر و پسندیده تر است.در دومین شکل از بالا می توانید بخش سرآیندهای برنامه را ببینید. همچنین این فایل دودویی اجرایی بر پایه Dynamic Linking است که از این رو کتابخانه های اشتراکی یا در لینوکس Shared Object (فایل های با پسوند so) به کار گرفته می شوند که شکل زیر برای نمونه برنامه GtkApp1 این کتابخانه های اشتراکی را نشان می دهد. https://virgool.io/linux-internals/%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%D9%87%D8%A7%DB%8C-%D8%A7%DB%8C%D8%B3%D8%AA%D8%A7-%D9%88-%D9%BE%D9%88%DB%8C%D8%A7-%D9%88-%D8%B4%DB%8C%D9%88%D9%87-%D9%87%D8%A7%DB%8C-linker-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-voruq0q7uju1 منبعبرای فراگیری بیشتر می توانید به سایت زیر نگاهی بیاندازیدhttp://sysadmingeeks.irhttps://dataset-academy.comو یا می توانید در کانال تلگرام عضو شوید.https://t.me/datasetacademydotcom</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Thu, 02 Jul 2020 16:20:07 +0430</pubDate>
            </item>
                    <item>
                <title>کتابخانه های ایستا و پویا و شیوه های Linker در برنامه نویسی</title>
                <link>https://virgool.io/linux-internals/%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%D9%87%D8%A7%DB%8C-%D8%A7%DB%8C%D8%B3%D8%AA%D8%A7-%D9%88-%D9%BE%D9%88%DB%8C%D8%A7-%D9%88-%D8%B4%DB%8C%D9%88%D9%87-%D9%87%D8%A7%DB%8C-linker-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-voruq0q7uju1</link>
                <description>دو روش برای ساخت یک برنامه دودویی اجرا شدنی یا Binary Executable هست: ۱) شیوه Static Linking و  ۲)  شیوه Dynamic Linking. در شیوه Static Linking از یک کتابخانه استاتیک یا Static Library کمک گرفته شده است.کتابخانه های ایستا و اشتراکی چه هستنددر این شیوه، برنامه موسوم به Linker (پیوند دهنده) همه ی کد تابع کتابخانه و همه داده ها را درون یک فایل دودویی اجرایی  با پسوند out برای نمونه a.out نگهداری می کند. البته این پسوند out اجباری نیست و می توانید آنرا ننوسید. در دستور زیر می بینید که خروجی دودویی اجرایی برنامه سی، بدست گزینه o- ساخته می شود که در اینجا آن را a.out نامگذاری کرده ایم ولی بایدی برای بودن پسوند out نیست. برای کامپایل یک برنامه نوشته شده به زبان C می توانیم از خط فرمان و از کامپایلر gcc (کوتاه شده GNU C Compiler) به گونه زیر کمک بگیریم:gcc my_c_program.c -o a.outاین شیوه پیوند دهنده ایستا خوب است، زیرا که هر آنچه که برای اجرای فایل دودویی اجرا شدنی نیاز داریم، همگی در یک فایل هستند، ولی اندازه فایل بسیار زیاد خواهد شد.شیوه دیگر، Dynamic Library است، که در آن به جای استفاده از Static Library، از Shared Library کمک گرفته می شود. در این شیوه، دیگر همه کتابخانه ها درون فایل a.out نگهداری نمی شوند، بلکه فراخوان هایی (Call) به تابع های استفاده شده به ریخت یک Directive در فایل a.out نگهداری می شوند.هرگاه که یک فایل a.out به گونه پیوند پویا را اجرا می کنید، وظیفه سیستم عامل است تا هم فایل a.out و هم کتابخانه های نیاز آن را درون حافظه بارگذاری کند. از این رو درون حافظه برنامه دودویی اجرا شدنی به کدهای مورد نیازش دسترسی دارد.بنابراین در شیوه پیوند پویا، به جای آن که کتابخانه ها به ریخت ایستا درون خود فایل a.out نگهداری شوند، هر زمان که برنامه a.out اجرا شد، سیستم عامل کتابخانه های نیاز را به درون حافظه بارگذاری می کند و از این رو از بزرگ شدن بی دلیل و بی سود فایل دودویی اجرایی، جلوگیری می شود.سودمندی های فایل a.out کاهش اندازه فایل بسیاری دیگر از برنامه ها، به کتابخانه های اشتراکی همسانی نیاز دارند که اکنون برای همگی در حافظه بارگذاری شده اند. چرایی برجسته دیگر برای به کار گیری Dynamic Linker در این است با دگرگونی در یک کتابخانه، دیگر نیازی نیست که خود فایل a.out را از نو کامپایل کنیم.در سیستم عامل ویندوز با واژه کوتاه شده DLL را شنیده باشید که کوتاه شده Dynamic Linking Librarie است. این کتابخانه های شناخته شده به نام DLL کتابخانه های اشتراکی هستند که در کنار (و نه درون) فایل دودویی اجرایی، در حافظه بارگذاری می شوند.در سیستم عامل لینوکس، کتابخانه های اشتراکی به نام Dynamically Loaded یا کوتاه شده DL شناخته می شوند. بنابراین کتابخانه های اشتراکی زمانی در حافظه بارگذاری می شوند که به آنها نیاز باشد و این نقطه پیش روی کتابخانه های ایستا است که همیشه درون فایل دودویی اجرایی هستند. کتابخانه های DL برای ماژول هایی پویا درون حافظه بارگذاری می شوند، بسیار سودمند و کاربردی هستند.توجه کنید، زمانی کتابخانه های اشتراکی به درون حافظه بارگذاری می شوند که یک برنامه دلخواه اجرا شده باشد. با اجرای یک برنامه، پیش از دادن پردازنده برای اجرا شدن آن، نیاز است تا آن برنامه در حافظه صف بندی شود و در همین زمان است که کتابخانه های آن به درون حافظه بارگذاری می شوند.منبعبرای فراگیری بیشتر می توانید به سایت زیر نگاهی بیاندازیدhttp://sysadmingeeks.irhttps://dataset-academy.comو یا می توانید در کانال تلگرام عضو شوید.https://t.me/datasetacademydotcom</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Thu, 02 Jul 2020 14:30:32 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش های رایگان کامپیوتر</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%87%D8%A7%DB%8C-%D8%B1%D8%A7%DB%8C%DA%AF%D8%A7%D9%86-%DA%A9%D8%A7%D9%85%D9%BE%DB%8C%D9%88%D8%AA%D8%B1-hfjhqdixfa0l</link>
                <description>با درود و خسته نباشیددر این مدت هر چند بسیار بسیار اندک تلاش کردم تا در سایت گوگل مجموعه ای از آموزش هایی درباره کامپیوتر را فراهم کنم.پیش از نوشتن در ویرگول، در سایت دیگری به نام http://dataset-academy.com می نوشتم و به امید خدا، بازهم خواهم نوشت.پیش از نوشتن در ویرگول، در سایت دیگری به نام https://dataset-academy.com می نوشتم و به امید خدا، بازهم خواهم نوشت.پس از انکه سایت بازدهی مالی درستی نداشت، برآن شدم تا محتوای آن را که باید بگویم نیاز به کار بیشتری دارد را از دیروز به رایگان در دسترس قرار دادم و به امید خدا از این پس نیز رایگان خواهم نوشت.بنابراین از شما می خواهم از این سایت را ببینید شاید مطلبی باشد که به کار شما بیایید.امیدوارم سودمند باشد.https://dataset-academy.com</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 05 Jun 2020 16:06:16 +0430</pubDate>
            </item>
                    <item>
                <title>سایت آموزش لینوکس پیشرفته</title>
                <link>https://virgool.io/linux-internals/%D8%B3%D8%A7%DB%8C%D8%AA-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA%D9%87-zalvgyyhmhgh</link>
                <description>با درود به شما دوستان گرامیسال نو شما شاد و خجسته بادآرزوی سالی سرشار از شادی و پیروزی و بهروزی و تندرستی و بی نیازی براتون دارمپس از زمانی که تصمیم داشتم سایتی درباره لینوکس و آشنایی با مفاهیم بنیادی سیستم عامل ها و هسته لینوکس راه اندازی کنم، چند روز پیش سایتی به نام http://sysadmingeeks.ir را راه اندازی کردم با انگیزه برای آموزش مفاهیم سیستم عامل، هسته لینوکس و برنامه نویسی سی. سایت در آغاز راه هست و من چون عادت دارم همیشه یک سری از آموزش های پیش زمینه رو آماده کنم تا به پیشرفته برسیم، پس نوشته های کنونی سایت هنوز وارد بحث های سیستم عامل و برخی دیگر از مفاهیم نشدند. به طور کلی انگیزه ام برای راه اندازی سایت در آغاز کار:آموزش زبان سی و ساختارهای دادهآموزش مفاهیم بنیادی سیستم عاملآموزش و نگاهی بر هسته لینوکس و زیر سیستم های آن همچون مدیریت حافظه تا زیر سیستم شبکهو اگر خدا یاری کند که بتوانم در آینده همچنان ادامه دهممفاهیم پایگاه داده و نگاهی بر الگوریتم های آنمفاهیم سیستم های توزیع شده از سیستم محاسبات توزیع شده مانند کلاستر تا HPC و گرید.پس شما رو دعوت می کنم سایت رو ببینید و در اینجا یا در خود سایت دیدگاه خودتان را به من بگوید.http://sysadmingeeks.irشاد باشید.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Sun, 29 Mar 2020 00:56:09 +0430</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش هشتم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%87%D8%B4%D8%AA%D9%85-g0duvfxiuz6l</link>
                <description>در نوشته پیشین تا اندازه ای درباره ساخت پیغام در سوکت های TCP و چالش پیش رو گفتیم. چالشی که بررسی شد، اندازه (Length) یک پیام یا داده فرستاده شدنی بود. چالش دیگری که پیش خواهد آمد، ترتیب بایت ها است. در نوشته زیر درباره دو مفهوم Big Endian و Little Endian گفتگو کردیم. https://virgool.io/@linux_internals/%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-little-endian-%D9%88-big-endian-rt5c3ailish0 همچنین در سری نوشته های &quot;آشنایی با سوکت های شبکه در سی و لینوکس&quot; درباره مفهوم Network Byte Order گفتیم که برای استاندارد سازی بایت های فرستاده شده در شبکه، از الگوی Big Endian کمک گرفته می شود تا مستقل از سیستم عامل یا سیستم های دو سوی شبکه، یک شیوه برای ترتیب بایت های شبکه به کار گرفته شود.حتی با به کارگیری از struct برای ساخت پیام ها برای پوشش اندازه پیام، بازهم ایرادی پیش خواهد آمد و این است که اگر قاعده ای پذیرفته شده برای ترتیب بایت شبکه نباشد، با اینکه داده ای درست به سوی دیگر فرستاده می شود ولی در سوی دیگر چون داده به گونه ای دیگری تفسیر و درک می شود، زیرا ترتیب بایت را متفاوت است.هچنین در نوشته های پیشین درباره چهار تابع به نام های ()htons و ()htonl و ()ntohs و ()ntohl گفته ایم که به ترتیب دو تای نخست برای تبدیل داده ها قابل خواندن برای کاربر به ترتیب بایت های شبکه (Big Endian) و دو تای پایانی برای تبدیل بایت های شبکه به نمایش قابل خوانده شدن توسط کاربر به کار گرفته می شوند.یادآوری: آنهایی که پایان نامشان s دارند برای داده های short که ۱۶ بیتی (۲ بایت) و آنهایی که l دارند برای داده های long که ۳۲ بیت (۴ بایت) هستند.msgStruct.dep = htonl(deposit);
msgStruct.wd = htonl(withdrawals);
send(s, msgStruct, sizeof(msgStruct), 0); https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B4%D8%B4%D9%85-siqfddwwsbd4  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%87%D9%81%D8%AA%D9%85-xs4cc4nzktkt هم تراز سازی و Paddingآنچه که از نوشته بخش هفتم تا کنون گفته شده است، درباره پیغام هایی است که میان دو سوی شبکه تبادل می شوند. در واقع می خواهیم پیام هایی را میان دو برنامه (یا فرایند) تبادل کنیم که از راه سوکت ها در روی شبکه با یکدیگر ارتباط دارند.این پیام رسانی (Message Passing) تنها برای دو فرایند یا برنامه بر روی دو رایانه در شبکه نیست و درون یک سیستم با چندین پردازنده (یا هسته) یا درون یک سیستم توزیع شده می تواند که نیاز باشد تا فرایندها با یکدیگر تبادل پیام بکنند.بنابراین در چنین موردهایی، باید در سطح برنامه (Application Layer) فرمت پیام بی ابهام شناسانده شده باشد و در بخش هفتم نشان دادیم که در زبان های سی و سی پلاس پلاس این کار (ساخت پیام با فرمت بی ابهام) به کمک struct انجام می شود.زمانی که پیام دارای چندین فیلد کد شده دودویی باشد، باید مفهومی به نام هم تراز سازی را در نظر بگیریم. هم تراز سازی داده ها یا ساختارهای داده (Data Structure Alignment)، نحوهٔ چینش و دسترسی به اطلاعات حافظه رایانه رایانه توسط پردازندهٔ رایانه است.در زبان های برنامه نویسی هر شی (متغیر) دارای دو شناسه مقدار و آدرس فضای حافظه اصلی است. داده ها در حافظه اصلی می توانند در اندازه های ۱، ۲، ۴، ۸ بایت یا به طور کلی توان هایی از دو نگهداری شوند. برای نمونه، می خواهیم در کنار مقدارهای int و ۴ بایتی سپرده و پرداخت ها، می خواهیم شمارِ تراکنش های سپرده ها و برداشت ها را با دو فیلد short int که هر یک ۲ بایت را اشغال می کنند، به گیرنده بفرستیم.توجه کنید برای این short int را برگزیدیم، زیرا که شمار سپرده ها و برداشتی ها بیش از ۶۵۵۳۵ نمی شود. بنابراین چیدمان یا تراز پیام دلخواه ما بدین گونه است که: ۴ بایت برای اندازه سپرده، ۲ بایت برای شمار تراکنش های سپرده، ۴ بایت برای پرداشت ها و در پایان ۲ بایت برای شمار تراکنش های برداشتی ها را در خود دارد.Message Alignmentstruct {
        int centsDeposited;
        unsigned short numDeps;
        int centsWithdrawn;
        unsigned short numWd;
} msgBuf;
// struct member value assignment
send(s, &amp;msgBuf, sizeof(msgBuf), 0);اندازه این struct باید ۱۲ بایت باشد ولی باید گفت که همیشه ماشین ها این (پیام) ۱۲ بایت را نمی سازند، بلکه ۱۴ بایت را خواهند ساخت. این دو بایت مازاد را Padding Bytes می گویند که در ساختار بالا و درون حافظه اصلی میان  numDeps و centsWithdrawn قرار می گیرد.برای تراز کردن داده ها در حافظه، یک یا چند بایت تهی (فضای آدرس حافظه اصلی) میان آدرس های حافظه که در هنگام اختصاص حافظه برای اعضای دیگر ساختار (struct) اختصاص داده شده است (یا خالی مانده) درج می شود. این مفهوم را Padding می نامند.چرایی اینکه این ۲ بایت مازاد پدید می اید برای این است که در پردازنده های معماری ۳۲ بیتی، پردازنده هر بار یک واژه (کلمه - Word) یا ۴ بایت را از حافظه بر می دارد. بنابراین برای برآوردن این نیاز، همیشه داده ها در ۴ بایت در حاظفه تراز می شوند. بنابراین Padding آدرس های مازاد و تهی است. Data Alignment with Padding Bytesراهکار برای پوشش و از میان برداشتن Padding چیست؟ راهکار بسیار ساده است و به کد نویسی باز می گردد. یک بار دیگر چرایی اینکه در دستورهای بالا Padding رخ داده است را می گوییم، زیرا دستور unsigned short numDeps را پیش از int centsWithdrawn نوشته شده است و یک فضای تهی ۲ بایتی را برای ساختن ۴ بایت نیاز خواهد داشت. پس اگر جای نوشتن متغیرها را مانند زیر تغییر دهیم دیگر Padding رخ نمی دهد.struct {
        int centsDeposited; 
        unsigned short numDeps;
         int centsWithdrawn;
         unsigned short numWd;
} msgBuf;بنابراین با کد بالا، چیدمان و تراز داده ها درون پیام (حافظه اصلی) به دسرتی انجام خواهد شد و اکنون پیام فرمتی همانند نخستین شکل با ۱۲ بایت را خواهد داشت. شاد و پیروز و تندرست و بی نیاز باشید.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 20 Mar 2020 21:54:25 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش هفتم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%87%D9%81%D8%AA%D9%85-xs4cc4nzktkt</link>
                <description>در نوشته بخش ششم درباره ساخت سوکت TCP گفته شد. در این نوشته می خواهم درباره چگونگی ساخت پیغام (Construct Message) برای پروتکل TCP در ارتباط شبکه به کمک سوکت آموزشی از کتاب TCP IP Sockets in C Practical Guide for Programmers و برخی دیگر از منابع بدهم. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B4%D8%B4%D9%85-siqfddwwsbd4 پروتکل TCP اتصال گرا (Connection Oriented) است و ارتباطی پایدار را میان دو سوی شبکه فراهم می کند ولی این پروتکل هیچ دیدی نسبت به پیغام های فرستاده شده ندارد. سوکت ابزاری برای ارتباط و تبادل پیغام و اطلاعات میان دو سوی شبکه است، از این رو، فرستنده و گیرنده باید بر سر اینکه چگونه این اطلاعات کد گذاری (Encode) شوند به توافق رسیده باشند.در واقع به دنبال یک پروتکل میان فرستنده و گیرنده هستیم که هر دو آن را پذیرفته اند. پروتکل به زبان ساده، یک دسته از قوانین و رویه ها است که میان دو نفر مشترک است. برای نمونه، زبان انگلیسی، امروزه پروتکلی است که دو نفر می توانند با آن و بر اساس یک سری از واژه و دستور زبان و جمله سازی، با یکدیگر گفتگو کنند.در رایانه ها نیز همین گونه است و پروتکل تنها در پیوند با لایه برنامه (Application Layer) نیست، بلکه در لایه های دیگر TCP/IP نیز پروتکل هایی فراهم شده اند که دو لایه همسان در دو سوی شبکه با یکدیگر گفتگو کنند. در همین راستا، در سوی فرستنده، در هر لایه از بالا به پایین، یک سری از اطلاعات به بسته شبکه (Network Packet) افزوده می شود که در سوی دیگر، در گیرنده، از پایین به بالا، این اطلاعات در همان لایه برداشته و خوانده می شوند.پروتکل به زبان سادهاطلاعات چگونه کد گذاری شوند.فرمت پیغام چیست.اندازه (Length) پیغام چه اندازه است.چگونه یک ارتباط با پایان یابد.پروتکل TCP بر پایه فریم ها (Frame) است و انعطاف بالایی را برای آماده سازی پیام ها می دهد. شکل زیر ساختار ساده ای از یک پیغام را نشان می دهد که در Cassandra به کار گرفته شده و CQL نام دارد. همانگونه که می بنید پیام از چندین فیلد (Field) جدا از هم ساخته شده است که هر فیلد یک داده ویژه را نگهداری می کند.CQL binary protocolآنچه که ما به دنبال آن هستیم، پروتکلی در سطح برنامه (Application Protocol) است که نیاز دارد تا آشکار بگوید که داده ها (پیغام ها) چگونه باید به دست فرستنده پیام فرمت شوند تا در سوی دیگر، گیرنده بتواند آن را پردازش و درک کند و داده هایی معنا دار را از آن بدست آورد.گمان کنید می خواهیم دو شماره int x, y را از یک برنامه به برنامه دیگر بفرستیم. برای یکپارچه بودن داده ها میان فرستنده و گیرنده، باید این دو داده به گونه ای توافق شده کدگذاری شوند وگرنه ایرادهایی پدید خواهد آمد. برای نمونه، داده های بانکی که باید فرستاده شوند که یکی از شماره ها نشان دهنده سپرده (Deposit) و دیگری نشان دهنده برداشت (Withdrawal) است. در این نوشته و بر پایه کتاب گفته شده چندین متغیر هست که در آن کتاب به کار رفته است.متغیر deposit برای اشاره به سپرده.متغیر withdrawals برای اشاره به برداشت ها.متغیر s که به توصیفگر فایل سوکت TCP اشاره دارد.برای ماشین و کامپایلر، اندازه (sizeof(int برابر با ۴ بایت و (sizeof(short برابر با ۲ بایت است.کدگذاری داده هابنابراین در اینجا به دنبال کد کردن این دو مقدار (متغیر) هستیم. یک راه این است که از کد گذاری نویسه ای (Character Encoding) کمک بگیریم. در واقع این دو مقدار شماره int را به رشته هایی از شماره های دهدهی چاپ شدنی کد می کنیم.یک کد گذاری ساده، کد گذاری اَسکی (ASCII) است که توالی از بایت ها است که هر مقدار آن متناظربا یک کد اسکی است. برای نمونه دو شماره 17998720 و 47034615 را می توانیم همانند شکل زیر در یک توالی از کدهای اسکی کد گذاری کنیم. در میان کدهای اسکی، کد شماره 48 برای شماره 0 و کد شماره 57 برای شماره 9 است. همچنین کد شماره 32 برای جدا کننده به کار رفته است، زیرا 32 کد اسکی تک فضای خالی (Space) است.ASCII Tableبنابراین در اینجا یک کد گذاری ساده برای دو شماره انجام دادیم که جدا کننده این دو شماره درون بایت کد شده فضای خالی است. در کنار به کارگیری از تک فضای خالی می توانستیم از کد اَسکی کاراکتر Null Terminator، یعنی کاراکتر 0\ یا از یک Tab کمک بگیریم. در شکل زیر که رشته کد شده را نشان می دهد، نخستین شماره برای سپرده و دومین برای برداشت ها است.Encoded Dataبنابراین اگر پیام آماده شده تنها در برگیرنده همین دو شماره باشد، پس اندازه آن ۱۸ بایت می شود. اکنون گمان کنید یک متغیر (کاراکتری از رشته ها) به نام msgBuffer داشته باشیم، می توانیم دو شماره (متغیر) را با تابع ()sprintf فرمت و آماده کنیم.sprintf(msgBuffer, &amp;quot%d%d &amp;quot,  deposit,  withdrawals);
send(s, msgBuffer, strlen(msgBuffer),  0);ایرادهاتوجه کنید که در پایان رشته کد شده نیز یک جدا کننده فضای خالی هست، زیرا با آن نیز مقدار برداشت شناخته می شود. اگر این نیز نباشد، پس برنامه (سوی دیگر شبکه) نمی تواند آنچه که به دنبال شماره برداشت شاید باشد را شناسایی کند.دومین ایراد این است که متغیری که بافر (در اینجا msgBuffer) را نگه می دارد، باید به اندازه ای کافی بزرگ باشد تا بیشترین اندازه بایت کد شده رادر خودش نگه دارد. به زبان ساده، باید همه رقم های شماره ها و همچنین در صورت بودن، علامت منفی، دو فضای خالی جدا کننده و کاراکتر Null Terminate را نیز نگه دارد.اگر هر شماره دارای ۹ رقم باشد، پس رشته کد شده نهایی ۲۳ بایت می شود، زیرا برای هر رقم ۲ بایت، برای هر فضای خالی نیز ۲ بایت و برای کاراکتر Null Terminate نیز ۱ بایت را در بر می گیرند. آیا این ۲۳ بایت اندازه ای برای رشته کد شده در برنامه است؟ اگر شماره ای چند رقم بیشتر داشته باشد، برنامه ار نخواهد کرد.سومین ایراد این است که در تابع ()send بالا، سومین ورودی، تابع ()strlen تنها بایت هایی را در نظر می گیرد که دو شماره را می سازند. به گفته دیگر، بایت پایانی، یعنی کاراکتر NULL را رَد می کند و از این رو، اندازه برگشتی رشته بایت کد شده، یکی کمتر خواهد بود.در کد زیر یک ماکرو تعریف شده است که اندازه بافر، یعنی ۱۳۲ بایت را مشخص می کند. سپس یک آرایه به نام msgBuffer ساخته شده که اندازه کلی آن برابر با ماکرو BUFSIZE است. سپس همه این آرایه ۱۳۲ بایتی بی توجه به اندازه پیام فرمت شده به گیرنده فرستاده می شود، پس در گیرنده، پیامی با اندازه ای بزرگ دریافت شده که تنها بخشی از آن داده های کد شده هستند.#define BUFSIZE 132
// Another Codes
char msgBuffer[BUFSIZE]
// Another Codes
sprintf(msgBuffer, &amp;quot%d%d &amp;quot,  deposit,  withdrawals);
send(s, msgBuffer,  BUFSIZE,  0);بنابراین کد گذاری شماره ها به رشته های (اَسکی)، شیوه کارآمدی نیست. هر بایت در رشته کد شده یکی از شماره های صفر تا نه است که هر شماره تنها ۴ بیت (و نه یک بایت) را نیاز دارد و این برای تغییر داده های شماره ای کد شده پسندیده نیست.برای نمونه، اگر نیاز باشد تا پردارشی (مانند جمع - تفریق) روی داده ها در سوی دیگر انجام دهیم، پس نیاز است تا یک تبدیل از String به Integer انجام شود. برای پوشش اندازه پیغام فرستاده شده، در زبان سی  ساختار ها (struct) برای ساخت پیغام به کار می رد.یک struct در زبان سی و سی پلاس پلاس، ساختاری است که از یک تا چندین عضو ساخته شده است که هر نوع می تواند از یک گونه بومی باشد. مانند int, float, double, char, bool یا آرایه ای از داده ها مانند [] int یا [] char) یا اشاره گر ها مانند * char که به یک رشته از توالی کاراکترها اشاره دارد. همچنین یک struct می تواند عضوی از گونه struct دیگری داشته باشد.از struct برای نمایش یک موجودیت مانند یک نفر کمک گرفته می شود. این نفر دارای نام، نام خانوادگی، سن، شمار فرزندان است. در کنار این، می تواند یک struct دیگر را درون خودش داشته باشد که به مشخصه های پدر و مادر او اشاره دارد.در زیر نمونه کدی نشان داده شده است که یک ساختار ساخته شده است. این ساختار یک الگو یا فریم پیام ساده TCP را نشان می دهد که دارای دو عضو به نام dep (اشاره به deposit) و wd (اشاره به withdrawals) از گونه int است.struct{
        int dep;
        int wd;
} msgStruct;
// Another Codes
msgStruct.dep = deposit;
msgStruct.wd   = withdrawals;
send(s, &amp;msgStruct, sizeof(msgStruct), 0);اندازه یک شی مانند int یا short در سی به کمک تابع ()sizeof بدست می آید. اندازه struct ها برابر با مجموع اندازه بایت هایی است که هر عضو آن اشغال می کند. برای نمونه int اندازه ۴ بایت را اشغال می کند، پس ساختار بالا در کل ۸ بایت را نیاز دارد، بی توجه به اینکه آن را به رشته اَسکی تبدیل کنیم که دارای یک کاراکتر NULL است.پروتکل TCP بسیار انعطاف پذیر است و می توانید دوبار به کمک ()send مقدار های متغیرهای deposit و withdrawals را بفرستیم. در واقع شیوه دیگر این است که در TCP خود متغیر را بفرستیم ولی این در UDP شدنی نیست، زیرا دو دیتاگرام (Datagram) جدا از هم برای هر متغیر فرستاده می شود.بنابراین در هر یک از دو شیوه (فرستادن تک تک متغیرها یا کمک از struct)، یک توالی از بایت ها همزمان فرستاده می شوند. این توالی از بایت ها از دو تا ۴ بایت برای هر int ساخته شده است. البته باز هم یک ایراد هست و این است که در ماشین (سیستم عامل) های گوناگون شاید نمایشی ناهمسان از int باشد که در این باره در نوشته های پیشین گفتیم روش استاندارد در شبکه، به کارگیری Big Endian یا Network Byte Order است.تا نوشته دیگر، شاد و پیروز و تندرست باشید.      </description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 20 Mar 2020 00:40:56 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش ششم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B4%D8%B4%D9%85-siqfddwwsbd4</link>
                <description>در دنباله نوشته های آشنایی با سوکت های شبکه در سی و لینوکس، در این نوشته می خواهیم چگونگی ساخت یک برنامه سوکت محور با سی و در سیستم عامل لینوکس را بر پایه پروتکل TCP نشان دهیم. سوکت های شبکه دارای آدرس فامیلی AF_INET برای IPv4 و AF_INET6 برای IPv6 هستند. همچنین اگر بخواهیم پروتکل TCP را به کار ببریم، باید SOCK_STREAM یا SOCK_DGRAM برای UDP را به دومین ورودی بفرستیم. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt فهرست فایل های سرآیند که نیاز هستندفایل stdio.h برای تابع های ()printf و ()fprintfفایل sys/socket.h برای تابع های ()socket و ()bind و ()connectفایل arpa/inet.h برای ساختار struct sockaddr_in و تابع ()inet_ntoaفایل stdlib.h برای تابع ()atoiفایل string.h برای تابع ()memsetفایل unistd.h برای تابع ()closeدر این نوشته از دو کد سرور و کلاینت این سایت کمک گرفته شده است، پس پیشنهاد می شود همزمان با خواندن این نوشته، این کدها را نیز داشته باشید.کد سروروظیفه سرور، گوش دادن به درخواست های ورودی از سوی کلاینت ها است، بنابراین کد (یا برنامه سرور) باشد نخست آماده و اتصالی را بر روی سوکت با نشانی IP یا شماره پورت برقرار کند. در سوی سرور نخست باید یک سوکت با ()socket ساخته شود که برگشتی این تابع یک شماره صحیح است که در واقع شماره توصیفگر فایل به سوکت است. همچنین می توانیم یک سری از گزینه ها را برای سوکت به کمک تابع ()setsockopt مشخص کنیم.در نوشته پَسین درباره این گزنه ها و تابع های ()setsockopt و ()getsockopt را آموزش خواهم داد.سپس باید با ساختار struct sockaddr_in یک دوتایی (IP, Port) را به همراه آدرس فامیلی مشخص می کنیم، زیرا هر سوکت یک دوتایی IP و Port است. سپس باید به کمک ()bind این دوتایی را به سوکت ساخته شده با ()socket انقیاد (Bind) کنیم.اکنون نوبت به فراخوانی تابع ()listen است، زیرا باید سرور آماده گوش دادن به درخواست های ورودی از روی شبکه باشد. یک درخواست از سوی کلاینت با دو مولفه نشانی IP و شماره پورت مشخص می شود. برای نمونه زمانی اگر فرض کنیم در یک شبکه محلی LAN، ماشین سروری هست که روی آن تنها یک کارت شبکه هست که نشانی آن 192.168.1.100 است و شماره پورت 9090 را مشخص کرده ایم، پس دوتایی سوکت سرور بر روی آن گوش می دهد و  کلاینت ها آن را برای یک درخواست به کار می برند، 192.168.1.100:9090 است.آدرس 0.0.0.0 به همه آدرس های روی یک ماشین اشاره دارد که در نوشته بخش چهارم گفتیم با INADDR_ANY مشخص می شود.تابع ()listen به درخواست های ورودی گوش می دهد و ر دنباله، تابع ()accept یک درخواست ورودی را می پذیرد. خروجی این تابع، یک سوکت تازه است که در واقع همانند ()socket، یک شماره شناسه برای توصفیگر فایل است.همانگونه که گفته شد، سوکت به ریخت فایل ها در لینوکس و سیستم عامل های شبه یونیکس پیاده سازی می شوند. بنابراین خواندن و نوشتن بر روی آنها در هسته، چیزی همانند خواندن و نوشتن روی فایل ها است. در واقع تابعی به نام ()read است که از روی توصیفگر فایل برگشتی از تابع ()accept، بافر به بافر می خواند.سرور در کنار اینکه می تواند از کلاینت ها پیغام ها و داده هایی را دریافت کند، می تواند به کمک تابعی به نام ()send به کلاینت پاسخی را نیز بفرستد که در ساده ترین گونه، یک پیغام ساده رشته ای است. بنابراین در سوی کلاینت به کمک ()recv، یک پیغام یا داده به سرور فرستاده شده است.شکل زیر چند خط نخستین از درون تابع ()main را نشان می دهد. در خط ۱۰ سه متغیر int تعریف شده است که به ترتیب برای ذخیره سازی برگشتی تابع های ()socket و ()accept و ()read نگهداری می شوند. سپس یک متغیر از نوع struct sockaddr_in ساخته ایم. متغیر opt از نوع int برای به کارگیری درون ()setsockoptبه کار می رود.تابع ()sizeof اندازه بایت های اشغال شده توسط یک متغیر را برگشت می دهد. در خط ۱۳ اندازه متغیر address که از نوع struct sockaddr_in است را در متغیر addrlen می رزیم. متغیر buffer آرایه ای کاراکترها یا رشته ای به طول 1024 است که سپس درون تابع ()read به کار می بریم تا بافرهای خوانده شده از روی سوکت در آن نگهداری شوند. در پایان یک اشاره گر از کاراکتر که در واقع رشته اَسکی است را نوشته ایم که پیغام پاسخ سرور به کلاینت را در خود نگهداری می کند.سپس در یک شرط if در خط های ۱۷ تا ۲۱ بررسی می شود که آیا توسکت به کمک تابع ()socket به درستی ساخته شده است. نتیجه برگشتی ()socket در صورت اجرای درست، باید شک شماره صحیح مثبت و نامنفی باشد. بنابراین شرط خط ۱۷ همین را بررسی می کند. توجه کنید چون می خواهیم برای IPv4 سوکت TCP بسازیم پس ورودی های یکم و دوم به ترتیب AF_INET و SOCK_STREAM هستند.تابع ()perror یک خطای سیستمی را بر روی Standard Error نشان می دهد. این تابع در stdio.h شناسانده شده است.تابع ()exit روند بیرون آمدن یا پایان یافتن برنامه را انجام می دهد. EXIT_SUCCESS و EXIT_FAILURE به ترتیب دو ثابت در سی استاندارد هستند که به همراه تابع ()exit در stdlib.h شناسانده شده اند.برای بیرون آمدن عادی و بی خطا در زبان های برنامه نویسی مانند سی و سی پلاس پلاس و پایتون، معمولا شماره صفر را به تابع ()exit می فرستند و از این رو ثابت EXIT_SUCCESS برابر با شماره صفر است. شماره 1- را نیز برای بیرون آمدن با خطا به کار می برند. البته می تواند شماره های دیگر مانند 2- را نیز برای شرایط دیگر خطا به کار برد.شرط if خط های ۲۳ تا ۲۷ نیز نخست تلاش می کند تا گزینه های سوکت را با ()setsockopt تنظیم کند. اگر این کار به خطا دچار شود، پس همانند پیش، تابع های ()perror و ()exit فراخوانی می شوند. در نوشته دیگری درباره گزینه های سوکت خواهم گفت.اکنون باید یک نمونه از ساختار struct sockaddr_in را مقداردهی کنیم . پیش از این متغیری به نام address را ساخته بودیم که اکنون مقدار هر عضو آن را مشخص کرده ایم. همچنین می بینید که به کمک ()htons شماره پورت را به بایت شبکه تبدیل کرده ایم. توجه کنید در خط ۳۱ نام یک ماکرو به نام PORT را به تابع ()htons فرستاده ایم که در واقع این ماکرو به کمک دستور زیر، پیش از تعریف تابع ()main انجام شده است.#define PORT 9090سپس باید به کمک ()bind نشانی IP و شماره درگاه را به سوکت انقیاد کنیم. ورودی یکم این تابع همان متغیری است که برآیند تابع ()socket است. ورودی دوم در شکل زیر نشان می دهد که یک تبدیل (Cast) از ساختار struct sockaddr_in به ساختار struct sockaddr است.در نوشته های پشین گفتیم که می توانیم ساختار struct sockaddr_in را به ساختار عمومی struct sockaddr تبدیل (Cast) کنیم.سپس باید تابع ()listen را فراخوانی کنیم که دو وروی را دریافت می کند. ورودی یکم نم متغیری است که برآیند تابع ()socket را در خودش نگه می دارد. ورودی دوم یک شماره صحیح که نام آن blocking است. این شماره، بیشینه اندازه یک صف انتظار اتصال ها را نشان می دهد که تا این اندازه می تواند رشد کند. توجه کنید برآیند ()listen نیز یک شماره صحیح (و نه یک شماره توصیفگر فایل) است که اگر کمتر از صفر باشد، پس خطایی رخ داده است.اکنون باید تابع ()accept فراخوانی شود که یک درخواست ورودی را می پذیرد. این تابع سه ورودی دارد که نخستین آنها نام متغیری است که برآیند ()socket در آن نگهداری می شود. دومین ورودی همانند ()bind یک تبدیل از struct sockaddr_in به struct sockaddr است.سومین ورودی یک تبدیل از int به socklen_t است. socklen_t یک گونه شناسانده شده در فایل sys/socket.h است که به گونه صحیح بی علامت ۳۲ بیتی اشاره می کند. توجه کنید متغیر addrlen که برآیند تابع ()sizeof را در خودش نگه می دارد از گونه int است و در سومین ورودی به socklen_t تبدیل می شود. همچنین توجه کنید که برآیند ()accept یک سوکت تازه است که در واقع به سوکت سوی کلاینت (در کد سرور) اشاره می کند که در اینجا نام آن new_socket است.تابع ()read برای خواندن داده هایی است که از سوکت فرستاد شده است و از این رو در سوی سرور، یکمین ورودی آن نام متغیری است که سوکت سوی کلاینت (در اینجا new_socket) را در خودش نگه می دارد. دومین ورودی نام متغیری است که قرار است بافر ورود ها باشد که در اینجا همان متغیر آرایه ای از کاراکترهای  ۱۰۲۴ بایتی است. سومین وررودی، اندازه ای به بایت است که نشان می دهد تا چه اندازه باید بایت به بایت بخوانیم که این همانند اندازه بافر (۱۰۲۴) بایت است.سپس با تابع ()printf رشته ورودی که در متغیر buffer هست را نشان می دهیم. سپس می توانیم با تابع ()send روی سوکت کلاینت بنویسیم. نخستین ورودی نام متغیری است که به سوکت سوی سرور اشاره می کند. دومین ورودی رشته یا متغیر رشته ای (در اینجا متغیر اشاره گر کاراکتری hello) است که می خوهیم به کلاینت فرستاده شود.کد کلاینتکد کلاینت نسبت به کد سرور، ساده تر و کوتاه تر است. در آن، همانند کد سرور، نخست باید یک سوکت بسازیم، زیرا کلاینت نیز باید یک نقطه پایانی برای فرستادن به و دریافت از نقطه دیگر داشته باشد. در ادامه کد کلاینت از همان سایتی که در بالا گفتم را توضیح می دهم ولی بخش هایی که از دید کد نویسی با کد سرور همسان هستند را نخواهم گفت.در آغاز دو متغیر به نام sock با مقدار پیش فرض صفر و valread از نوع int ساخته ایم. متغیر sock سپس برای برآیند تابع ()socket و valread برای نگهداری برآیند تابع ()read به کار می روند. متغیر دیگر ser_addr است که نمونه ای از ساختار struct sockaddr_in است که قرار است نشانی IP و شماره درگاه سرور را در کلاینت نشان دهد. در پایان دو متغیر hello و buffer که کاربردی همانند کد سرور دارند. در خط های ۲۱ و ۲۲ شکل زیر می توانید ببینید که عضوهای این سوکت مقداردهی شده اند.در خط ۱۸ می بینید که برای بیرون آمدن از برنامه در صورت بروز خطا، از دستور return -1 کمک گرفته شده است. این همسان با (exit(EXIT_FAILURE است، زیرا EXIT_FAILURE نیز شماره ای صحیح و منفی است.سپس تابع ()inet_pton برای تبدیل رشته نشانی IP (در اینجا 127.0.0.1) به بایت دودویی شبکه به کار گرفته می شود. سپس باید به کمک تابع ()connect به سرور (سوکت سرور) وصل شویم. ورودی یکم این تابع، نام متغیری است که سوکت کلاینت را نگه می دارد که در اینجا sock نام دارد. ورودی دوم یک تبدیل (Cast) از ساختار struct sockaddr_in به struct sockaddr است. در واقع ورودی دوم سوکت سرور را Cast می کند. اگر برآیند انجام ()connect کوچکتر از صفر باشد، پس خطایی رخ داده است. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c سپس باید یک پیغام یا داده به سرور فرستاده شود که این کار بدست تابع ()send انجام می شود. پس از فرستادن پیغام به سرور، کلاینت منتظر پاسخ می ماند که این پاسخ به کمک تابع ()read از روی سوکت خوانده می شود.بنابراینکلاینت آغاز کننده ارتباط است و به سوکت شبکه وصل می شود.کلاینت نخست داده می فرستد و سپس در انتظار پاسخ ی ماند.سرور نخست پیغامی را می گیرد و سپس پاسخی را می فرستد.در سوی کلاینت باید ویژگی های سوکت شبکه را برای اتصال به آن داشته باشیم.شاد و پیروز و تندست باشید.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 18 Mar 2020 14:47:44 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش پنجم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c</link>
                <description>در این نوشته می خواهیم برخی نکته ها و تابع هایی که در برنامه نویسی سوکت نیاز هستند را به شما بگویم تا در نوشته های دیگر از پیش با آنها آشنا باشید. جدول زیر فهرستی از گونه های کاربردی در برنامه نویسی سی و سوکت نویسی را نشان می دهد. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt Data Typesاندازه ساختار سوکتبرای نمونه sa_family_t آدرس فامیلی سوکت مانند AF_INET یا AF_INET6 را نگهداری می کند که در واقع شماره های صحیحی هستند که به ریخت ماکرو شناسانده شده اند. socklen_t نیز یک گونه است که اندازه یک سوکت یا اندازه یک ساختار سوکت را نگهداری می کند. اندازه هر گونه داده مانند int یا struct ها را به کمک تابع ()sizeof بدست می آوریم.ساختار struct sockaddr_in دارای عضوهای گوناگونی از گونه ها است که هر یک اندازه ویژه خودش را دارد. برای نمونه عضو sin_addr که از گونه in_port_t است، اندازه اش ۱۶ بیت یا دو بایت است، زیرا in_port_t گونه ای صحیح بی علامت ۱۶ بیتی است. اندازه یک ساختار در زبان سی برابر با مجموع  اندازه همه عضوهای آن است. توجه کنید خود عضو sin_addr نمونه ای از یک ساختار دیگر به نام struct in_addr است، پس اندازه خود sin_addr برابر با اندازه همه عضوهای ساختار struct in_addr است که با اندازه دیگر عضوها جمع می شود.دیگر تابع های تبدیل در سوکت نویسیدر نوشته های پیشین درباره چهار تابع برای تبدیل آدرس و شماره پورت به بایت شبکه گفته ام و در اینجا یک دسته دیگر از تابع هایی که برای تبدیل آدرس های IP (نسخه ۴ یا ۶) به بایت های شبکه به کار می روند. این سه تابع در arpa/in.h شناسانده شده اند.تابع ()inet_aton یک رشته از کاراکترهای سی که یک آدرس IP را نشان می دهد را به بایت های دودویی شبکه تبدیل می کند. اگر آدرس معتبر و درست باشد، این تابع مقداری غیر صفر را برگشت می دهد وگرنه صفر برگشت داده خواهد شد.int inet_aton(const char *cp, struct in_addr *inp)در کد بالا که از رهنمای man inet_aton برداشته شده است، نمونه ای از کاربرد آن نشان داده شده است. نخست یک نمونه از ساختار struct addr_in ساخته ایم، زیرا دومین ورودی ()inet_aton یک گونه از struct in_addr است. در خط ۱۵ می بینید که آدرس متغیر addr دمین ورودی تابع است.نخستین ورودی تابع یک رشته است که آدرس IP (نسخه ۴) را مشخص می کند که باید به بایت های شبکه تبدیل شده و در متغیری که آدرس آن به دومین ورودی فرستاده شد، ذخیره شود. بنابراین دومین ورودی، فراخوانی یک متغیر با ارجاع (Call by Reference) است.در کد بالا نخست از خط فرمان یک ورودی خوانده می شود و سپس این ورودی به عنوان نخستین عنصر با اندیس صفر در آرایه رشته []argv نگهداری می شود. سپس این ورودی که یک رشته برابر با IP مانند 192.168.1.100 است به ورودی یکم فرستاده می شود.بنابراین رشته ای مانند 192.168.100 که قابل خواندن برای کاربران است به بایت های دودویی قابل استفاده در ماشین و شبکه تبدیل می شوند. توجه کنید که اگر آدرس IP معتبر باشد، برآیند تابع شماره ای غیر صفر است وگرنه پیغام خط ۱۷ نشان داده می شود و برنامه با نادرستی و بدست تابع ()exit پایان می یابد.تابع دیگر ()inet_ntoa است که در خط ۲۱ فراخوانی شده است و کاربردی وارونه ()inet_aton دارد. توجه کنید که ()inet_aton برای تبدیل رشته اسکی a به بایت شبکه n دارد ولی ()inet_ntoa برای تبدیل بایت شبکه n به رشته اسکی a قابل خوانده شدن بدست کاربران به کار می رود.char *inet_ntoa(struct in_addr in)توجه کنید ()inet_ntoa تنها یک ورودی دارد که آن نام متغیری از struct in_addr است و فراخوانی در ()inet_ntoa فراخوانی با مقدار (Call by Value) است. همچنین تابع ()inet_ntoa یک رشته از کاراکترها (* char) را برگشت می دهد که همان نشانی IP قابل خوانده شدن توسط کاربران است. تابع دیگر ()inet_addr است که یک ورودی رشته از کاراکترها دریافت کرده و سپس یک گونه از in_addr_t را برگشت می دهد.in_addr_t inet_addr(const char *cp);تابع دیگر ()inet_pton است که یک نشانی IPv4 یا IPv6 را از رشته ای به کد دودویی تبدیل می کند. این تابع سه ورودی دریافت می کند. نخستین ورودی یک آدرس فامیلی AF_INET یا AF_INET6 است. دومین ورودی یک رشته است که آدرس مبدا مانند 192.168.1.100 در IPv4 را مشخص می کند. سومین ورودی یک اشاره گر void است که آدرس دومین ورودی تبدیل شده در فامیلی آدرس نخستین ورودی در آن نگهداری می شود.int inet_pton(int af, const char *src, void *dst)در کد زیر نمونه ای از تبدیل آدرس های IPv4 و IPv6 به بایت های شبکه نشان داده شده است. نخست یک متغیر به نام buf و به اندازه یک ساختار struct in6_addr تعریف کرده ایم. توجه کنید ساختارهای in_addr و in6_addr به ترتیب IPv4 و IPv6 را نشان می دهند.در دنباله دو متغیر domain و s از گونه int و یک آرایه از کاراکترها به اندازه INET6_ADDRSTRLEN را ساخته ایم. سپس در شرط خط های ۱۲ تا ۱۶ بررسی می شود که آیا ورودی پارامترهای ورودی کمتر از سه تا نباشد. توجه کنید زمانی که می خواهیم با argc و argv ورودی از خط فرمان دریافت کنیم، argc به تعداد پارامترهای ورودی اشاره دارد که نخستین آنها نام برنامه و دیگر ورودی ها پارامترهایی هستند که در برنامه استفاده می شوند یا بر روند اجرای برنامه تاثیر می گذارند. بنابراین [0]argv به نخستین پارامتر ورودی۷ یعنی نام برنامه اجرایی اشاره دارد.برنامه بدین صورت است که باید یکی از آرگومان های i4 یا i6 که در ورودی و پس از نام برنامه مشخص شده باشد که از طریق [1]argv مشخص می شود. اگر پارامتر دوم i4 باشد، پس آدرس فامیلی AF_INET و اگر i6 باشد پس AF_INET6 خواهد بود.از تابع ()strcmp برای سنجش اندیس دوم argv با یکی از دو مقدار رشته i4 یا i6 استفاده شده است. به هر حال اگر دو رشته فرستاده شده به ()strcmp یکسان باشند، پس مقدار صفر برگشت داده می شود. توجه کنید نتیجه خط ۱۸ که یا AF_INET یا AF_INET6 است، در متغیر domain نگهداری می شود که سپس این متغیر نخستین ورودی تابع ()inet_pton خواهد بود.دومین ورودی تابع، سومین پارامتر ورودی از خط فرمان است که در [2]argv نگهداری می شود. سومین پارامتر ورودی نیز که نتیجه اجرای تابع در آن ریخته می شود، متغیر buf است. متغیر s برآیند تابع ()inet_pton است. تابع ()inet_pton هم برای IPv4 و هم برای IPv6 به کار می رود. تابع دیگر ()inet_ntop است که کاربردی وارونه ()inet_pton دارد.const char *inet_ntop (int family, cost void *addrptr, char *strptr, size_t len)در فایل netinet/in.h دو کاکرو به نام های INET_ADDRSTRLEN با مقدار ۱۶ و INET_ADDRSTRLEN با مقدار ۶۴ شناسانده شده اند که به ترتیب اندازه رشته (STRLEN) برای آدرس (ADDR) نسخه ۴ و ۶ را نشان می دهند. در واقع با رشته ای ۱۶ بیتی می توانیم IPv4 و با رشته ای ۴۶ بیتی می توانیم IPv6 را نشان دهیم.این اندازه ها با حساب یک بیت برای کاراکتر پایانی رشته ها در سی، یعنی 0\ یا Terminate Character حساب شده اند. به هر رو، اگر اندازه تعیین شده (در اینجا برای متغیر buf) کم باشد، یک اشاره گر تهی (Null Pointer) برگشت داده می شود، از این رو در زمان تعریف آرایه buf بیشترین مقدار را صرف نظر از IPv4 یا IPv6 در نظر گرفته شد است.شاد و پیروز و تندرست باشید.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 18 Mar 2020 14:02:24 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش چهارم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt</link>
                <description>در دنباله سری آموزش های آشنایی با سوکت های شبکه در سی و لینوکس، در این نوشته می خواهم درباره برخی از تابع هایی گفتگو کنم که برای تبدیل نشانی های IP به کار می روند. کاربرد این تابع برای تبدیل یک نشانی IP اَسکی و قابل خوانده شدن توسط ما به ریخت بایتهای دودویی است که توسط ماشین قابل درک شدن هستند.برای نمونه نشانی 192.168.1.100 یا نشانی - 0:0:0:0:0ffff:c0a8:164 برای ما قابل خواندن و درک شدن است ولی ماشین که می خواهد به کمک لایه های TCP/IP بسته شبکه (Network Packet) را آماده کند و در پایان بر روی اینترنت قرار داده و به به ماشین دیگر بفرستند، نیاز دارد تا بایت های دودویی صفر و یک را داشته باشد. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig ترتیب بایت شبکهدر رایانه ها (چه دسکتاپ، سرور،موبایل یا هر ابزار دیگری) دو شیوه Little Endian و Big Endian برای ذخیره سازی بایت ها درون حافظه و دیسک ها هست. برای نمونه در نگهداری 56a7 نخست بایت های 56 و سپس بایت های a7 نگهداری می شوند که این شیوه Big Endian است.ولی بیشتر سیستم های عامل مانند لینوکس، ویندوز و مکینتاش (و شاید همه BSD ها) شیوه Little Endian را به کار می برند به گونه ای که نخست بایت های a7 و سپس 56 نگهداری می شوند. سیستم عامل سولاریس شیوه Big Endian را به کار برده است. https://virgool.io/@linux_internals/%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-little-endian-%D9%88-big-endian-rt5c3ailish0 بنابراین رایانه ها یک شیوه یکپارچه و همگانی برای نگهداری بایت ها را به کار نمی برند و از این برای آنکه رایانه ها و سیستم عامل های گوناگون بتوانند بر روی اینترنت و شبکه با یکدیگر در هم کنشی (تعامل) باشند، پس پروتکل های اینترنتی باید یک رویکرد یکپارچه و همگانی برای ترتیب بایت ها را به کار ببرند، زیرا قاعدتا نبودن این شیوه یکپارچه، باعث می شود در سوی دیگر، داده نادرست تفسیر شود. این شیوه یکپارچه برای ترتیب بایت های فرستاده شده روی شبکه را ترتیب بایت شبکه (Network Byte Order) می گویند.بنابراین زمانی که می خواهیم یک سوکت شبکه را بسازیم، می بایست که اطمینان داشته باشیم که داده های درون عضوهای sin_addr و sin_port از ساختار struct sockaddr_in برای IPv4 و struct coakaddr_in6 برای IPv6 ترتیب بایت شبکه را داشته باشند. برای براوردن این، دو دسته از تابع ها فراهم شده است.تابع هایی که نشانی هاست (IP) را به ترتیب بایت شبکه تبدیل می کنند که دو تابع ()htons و ()htonl در این دسته هستند.تابع هایی که ترتیب بایت شبکه را نشانی هاست (IP) تبدیل می کنند که دو تابع ()ntphs و ()ntohl در این دسته هستند.Network Byte Orderبنابراین دو دسته تابع با نام هایی به ریخت H-to-N که برای تبدیل نشانی های IP به جریان بایت های دودویی شبکه و وارونه آن، N-to-H هستند که جریان بایت های دودویی شبکه را به نشانی های IP قابل خوانده شده تبدیل می کنند. این چهار تابع به گونه ماکروها در فایل سرآیند arpa/inet.h شناسانده شده اند و از این رو برای به کارگیری آنها در فایل سی باید سرآیند arpa/inet.h را include# کنیم.همچنین این تابع همگی به دو دسته short (پایان نام s) و long (پایان نام l) دسته بندی می شوند. unsigned short گونه ۱۶ بیتی (۲ بایتی) و unsigned long گونه ۳۲ بیتی (۴ بایتی) است. در کد سی زیر می توانیم بررسی کنیم سیستم عاملی که کد درون آن انجام شده Big Endian یا Little Endian است.نمونه کد سی برای تشخیص سیستم Endianنخست در خط های ۳ و ۴ دو ماکر به نام های BIG_ENDIAN و LITTLE_ENDIAN با مقدارهای 0 و 1 نوشته شده است. سپس یک تابع به نام ()TestByteOrder که مقداری int را برگشت می دهد را نوشته ایم. درون تابع نخست یک متغیر short int به نام word با مقدار 0x0001 شناسانده ایم و در دنباله این مقدار int را به رشته از کاراکترها تبدیل (Cast) کرده ایم که برآیند در متغیری به نام b نگهداری می شود.درون عبارت پیش روی return که همانند if..else است، بررسی می کنیم که آیا عنصر نخست درون رشته b برابر با شماره ای است که در ماکرو BIG_ENDIAN نگهداری می شود یا وگرنه برابر با مقداری است که در ماکرو LITTLE_ENDIAN نگهداری می شود.اگر سیستم عامل از Big Endian پشتیبانی می کند پس بایت 00 شماره 0x0001 باید نخست نگهداری شود که برابر با مقدار 0 است که در ماکرو  BIG_ENDIAN نگهداری می شود وگرنه اگر از LITTLE_ENDIAN پشتیبانی کند، پس بایت 01 نخست نگهداری می شود که برابر با مقدار 1 است که در ماکرو  LITTLE_ENDIAN نگهداری می شود.Linux Support Little Endianکد زیر نمونه ای ساخت سوکت با ()socket و چگونگی مقداردهی درست عضوهای ساختار struct sockaddr_in را نشان می دهد. نخست دو متغیر int به نام port و ip با مقدارهای 9090 و INADDR_ANY را نوشته ایم. INADDR_ANY یک ماکرو است که در فایل سرآیند netinet/in.h شناسانده شده است و به نشانی 0.0.0.0 اشاره دارد.در IPv4 نشانی های ویژه ای هستند، مانند 127.0.0.1 که نشانی Loop Back یا نشانی به ماشین محلی یا لوکال هاست است. نشانی دیگر، 0.0.0.0 است که در واقع زمانی که بخواهیم به همه کارت های شبکه اشاره کنیم، می توانیم  0.0.0.0 را به کار ببریم.گاهی بر روی سرور چندین اینترفیس شبکه است و برای اینکه سوکت را به گونه ای بسازیم که بتواند بر روی شمار پورت و بر روی همه این آدرس ها گوش دهد، پس می توانیم جای تک تک آدرس های IP، نشانی 0.0.0.0 را به کار ببریم که در زبان سی ماکرو INADDR_ANY که int هست به این نشانی اشاره می کند.سپس یک سوکت UDP ساخته ایم زیرا که دومین ورودی SOCK_DRAM است و فامیلی آدرس آن IPv4 است، زیرا که ورودی یکم آن AF_INET است. سپس یک نمونه از ساختار sockaddr_in ساخته ایم و همانگونه که پیش از این گفته شد، باید با متدهای H-to-N شماره پورت و نشانی IP را ابه بایت شبکه تبدیل کنیم.htons() - htonl()شماره های پورت ۱۶ بیتی یا ۲ بایتی و دربازه شماره صفر تا ۶۵۵۳۵ هستند، پس ()htons را به کار برده ایم و چون شمارهای IPv4 برابر با ۳۲ بیت یا ۴ بایت هستند، پس ()htonl را به کار برده ایم. آنچه که در کد بالا گفته شد، یک نمایش از چگونگی ساخت سوکت است که با فراخوانی متد ()socket و سپس ساخت یک نمونه از ساختار struct sockaddr_in برای IPv4 انجام می شود.در کد بالا فرض بر نوشتن سوکت سرور است ولی همه چیز را نشان نمی دهد. در دنباله کد باید آدرس سوکتی IPv4 که در برگیرنده شماره پورت server_socket.sin_port و نشانی IP یعنی server_socket.sin_addr.s_addr را باید پس از این به سوکتی که فایل توصیفگر آن را ساخته ایم انقیاد (Bind) کنیم که این کار توسط تابع ()bind انجام می شود. در واقع با ()bind است که می گویم سوکت ساخته و نگهداری شده در (اینجا) متغیر server_socket_fd بر روی کدام نشانی (ها) و شماره پورت گوش دهد.شاد و پیروز و تندرست باشید.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 13 Mar 2020 15:06:57 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش سوم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig</link>
                <description>در بخش های پیشین درباره سوکت های اینترنت (Internet Socket) و ساختارهای درون هسته لینوکس برای نمایش یک سوکت گفتیم. در دنباله آموزش، در این نوشته می خواهیم با تابع ()socket و مفاهیمی همچون آدرس فامیلی (Address Family) و گونه های سوکت گفتگو کنیم.تابع ()socketدر هر دو سوی کلاینت و سرور، نخستین گام برای ساخت یک سوکت، فراخوانی و مقداردهی درست تابع ()socket است. بر پایه کد زیر، این تابع سه ورودی را دریافت می کنند که به ترتیب آدرس فامیلی، نوع سوکت و پروتکل را نشان می دهند. مقدار برگشتی این تابع نیز بر پایه آنچه که در بخش یکم گفتیم، یک شماره صحیح است که در واقع یک توصیفگر فایل (File Descriptor) به یک فایل سوکت باز شده است.int socket(int domain, int type, int protocol); https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/آشنایی-با-سوکت-های-شبکه-در-سی-و-لینوکس-بخش-دوم-e4ku3bqi7tsj پارامتر domain آدرس فامیلی را مشخص می کند که می تواند یکی از چندین مورد باشد که سه مقدار AF_INET و AF_INET6 یا AF_RAW برخی از آنها هستند. چون می خواهیم سوکت هایی روی شبکه (اینترنت سوکت) را بسازیم، پس اگر نشانی IP به کار رفته IPv4 باشد، پس ورودی نخست AF_INET وگرنه برای IPv6 برابر با AF_INET6 است.آدرس فامیلی گونه یا فرمت آدرس ورودی را برای سوکت نشان می دهد. برای نمونه نشانی 192.168.1.100 یک IPv4 خصوصی (محلی) برای رایانه شما است و نشانی - 0:0:0:0:0ffff:c0a8:164 نسخه IPv6 آن است. بنابراین برای ارتباط ها بر پایه IPv4 باید از AF_INET و بر پایه IPv6 از AF_INET6 کمک بگیریم.پارامتر type گونه ارتباط میان دو سو را نشان می دهد که چون داریم درباره سوکت های اینترنت می گویم، پس ارتباط می تواند TCP یا UDP باشد. اگر می خواهیم ارتباط از نوع TCP باشد، پس باید مقدار SOCK_STREAM وگرنه برای UDP باید مقدار SOCK_DGRAM را به کار ببریم.پروتکل TCP یک پروتکل امن، پایدار و دو سویِ (دو طرفه - Two Way)، بر پایه اتصال (Connection Based) است در حالی که UDP بر پایه دیتاگرام (DGRAM = DataGRAM)، ناپایدار و بی اتصال (Connection Less) است.فهرستی فراگیر از همه گزینه ها برای آدرس فامیلی و نوع ارتباط را می توانید از اینجا بخوانید یا در لینوکس خود دستور man 2 socket را اجرا کنید.سومین ورودی که protocol نام دارد، برای ساخت سوکت های اینترنت TCP و UDP همیشه دارای مقدار صفر است. توجه کنید هر سه ورودی ()socket از گونه int هستند و در واقع AF_INET و AF_INET6 و SOCK_STREAM و SOCK_DGRAM و دیگر گزینه ها، همگی به یک شماره صحیح اشاره دارند. همگی این گزینه ها در فایل سرآیند sys/socket.h به ریخت ماکروهای سی (دستورهای define) همانند شکل زیر شناسانده شده اند.Socket Macrosبر پایه شکل بالا می توانید ببینید که AF_INET برابر با ۱ و AF_INET6 برابر با ۱۰ است و SOCK_STREAM و SOCK_DGRAM برابر با ۱ و ۲ هستند. کدهای زیر به ترتیب سوکت های TCP و UDP را ساخته اند و از این رو متغیر های tcp_socket و udp_socket به ترتیب دو توصیفگر فایل هستند که از این پس برای اشاره به سومت ها به کار رفته و به دیگر تابع های فرستاده می شوند.tcp_socket = socket(AF_INET, SOCK_STREAM, 0);udp_socket = socket(AF_INET, SOCK_DGRAM, 0);</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 11 Mar 2020 20:35:41 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش دوم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj</link>
                <description>در دنباله نوشته های برنامه نویسی و آشنایی با معماری شبکه در لینوکس، در دومین نوشته از دسته نوشته های آشنایی با سوکت های شبکه در سی و لینوکس، می خواهم کمی درباره پیاده سازی آدرس IP4 (یا IPv4) در هسته لینوکس بگویم.همانند دیگر مولفه های یک سیستم عامل مانند مدیریت فرآیندها، سیستم فایل، دیوایس های سخت افزای و دیگر مولفه ها، مولفه شبکه و زیر مولفه های آن درون هسته لینوکس پیاده سازی شده اند. هسته لینوکس بر پایه سی و تا اندازه ای اسمبلی (برای نمونه در بوت شدن هسته) نوشته شده است.ساختار ها یا Structure ها در هسته لینوکسسی زبانی رویه ای (بر پایه تابع ها) است و زمانی که شما هسته لینوکس را بررسی می کنید، بسیار با تابع ها، اشاره گرها و به ویژه ساختارها یا همان Structure ها بر می خورید. در واقع این ساختارها، نوع های داده ای هستند که در برنامه نویسی در سطح یا فضای کاربر، به کار گرفته می شوند.هر یک از این ساختارها درون یکی از فایل سرآیند هسته لینوکس پیاده سازی شده اند. برای نمونه، ساختاری که یک کاربر لاگین کرده را نشان می دهد، در فایل سرآیند pwd.h پیاده سازی شده است. توجه کنید که یک ساختار یا struct در سی، دارای عضوهایی است که از طریق نام آن ساختار در دسترس هستند. به عبارت دیگر، یک کاربر با یک struct و هر ویژگی آن کاربر نیز با یکی از عضوهای struct پیاده سازی شده است.ساختار آدرس سوکت عمومیبرنامه هایی که سوکت را به کار می برند، نیاز دارند تا این توانایی را داشته باشند که نشانی اینترنت (IP) و شماره درگاه (Port) را برای هسته لینوکس مشخص کنند. برای نمونه کلاینت باید نشانی و شماره درگاه از پیش مشخص شده روی سرور را باید در خود مشخص کند تا هسته از مقصد بسته (Packet) آگاه باشد.در کنار این، نیاز است تا آدرس به برنامه فرستاده شود. برای نمونه، در پیاده سازی یک همانند Caller Id در تلفن ها که شماره تماس گیرنده نشان داده می شود، سرور باید این توانایی را داشته باشد که نشانی هر کلاینتی که با او ارتباط برقرار می کند را بخواند.struct sockaddrشکل بالا ساختار struct sockaddr که ساختار آدرس سوکت عمومی (Generic Socket Address Structure) را نشان می دهد. این ساختار اطلاعات آدرس سوکت را برای بسیاری از نوع های سوکت نگهداری می کند.عضو sa_family که از نوع unsigned short است، سوکت آدرس فامیلی (Address Family) را نشان می دهد که در ادامه درباره آن گفته شده است. برای ساخت سوکت برای IPv4 باید آدرس فامیلی AF_INET و برای IPv6 باید AF_INET6 را به کار ببریم. اندازه sa_family دو بایت است زیرا اندازه فضای اشغالی برای unsigned short برابر با دو بایت است.توجه کنید متغیری که از نوع unsigned short باشد می تواند مقداری میان بازه صفر تا ۶۵۵۳۵ را دریافت کند.عضو دیگر sa_data است که به گونه یک رشته (آرایه ای از کاراکترها) به اندازه ۱۴ بایت شناسانده شده است. این عضو اطلاعاتی همچون نشانی IP و شماره درگاه مقصد را نگه می دارد. شماره پورت ها، شماره ای در بازه صفر تا ۶۵۵۳۵ استو می توان با ۲ بایت یا ۱۶ بیت نمایش داد و نشانی IPv4 نیز ۳۲ بیتی یا ۴ بایتی هستند.ساختار آدرس سوکتساختار آدرس سوکت (Socket Address Structure) یا SAS یکی از چندین struct درون هسته لینوکس هستند. توجه کنید دو سوکت برای IPv4 و IPv6 داریم و از این رو به ازای IPv4 و IPv6 ساختارهای جدای از هم برای سوکت ها پیاده سازی شده است. برای پیاده سازی یا نمایش یک سوکت IPv4 در هسته لینوکس، دو ساختار به نام های struct in_addr و struct sockaddr_in پیاده سازی شده است که در آنها in کوتاه شده Internet است، زیرا در کنار سوکت های شبکه که ارتباط میان دو فرآیند در دو سوی شبکه را فراهم می کنند، سوکت های دیگری نیز در لینوکس هستند.struct sockaddr_in - struct in_addr IPv4ساختار struct sockaddr_inاین ساختار دارای سه عضو به نام های sin_family از نوع sa_family_t و sin_port از نوع in_port_t و sin_addr از نوع ساختار دومی، یعنی struct in_addr است. اگر نوشته بخش یکم را به یاد داشته باشید، گفته شد که یک سوکت در برگیرنده یک دوتایی (IP, Port) است که در struct sockaddr_in می بینید که دو عضو sin_port و sin_addr به ترتیب به این دو اشاره دارند. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm واژه sin کوتاه شده socket internet است.نوع sin_port به گونه in_port_t است که در واقع یک نوع تعریف شده در سی است که به نوع uint16_t یا Unsigned Integer 16 bit اشاره می کند. خود in_port_t در فایل سرآیند به نام netinet/in.h و uint16_t نیز در فایل سرآیند inttypes.h شناسانده شده است. در واقع uint16_t یک مقدار صحیح ۱۶ بیتی به علامت (مثبت) است که بیشترین مقدار آن برابر با ۶۵۵۳۵ است و چون in_port_t نیز به uint16_t اشاره دارد، پس می توان با آن یک شماره پورت از صفر تا بیشترین و بالاترین شماره، یعنی ۶۵۵۳۵ را نگهداری کرد.توجه کنید تعداد یا بازه شماره پورت ها از شماره صفر تا ۶۵۵۳۵ است که این برپایه استاندارد IEEE است.عضو دیگر، یعنی sin_len از نوع شماره صحیح بی علامت ۸ بیتی uint8_t است که به منظور پشتیبانی از BSD 4.3 به بعد به ساختار struct sockaddr_in افزوده شده است و هرگز استفاده و مقداردهی (تنظیم) نمی شود. اگر زمانی راهنمای man ip را در لینوکس خواندید، شاید این عضو در ساختار نوشته شده در راهنما نباشد و نخستین عضو sin_family باشد. آدرس فامیلی که در نوشته دیگری درباره آن خواهم گفت، برای IPv4 همیشه برابر با AF_INET خواهد بود.برای برنامه نویسی سوکت در لینوکس، تنها سه عضو sin_family و sin_port و sin_addr نیاز هستند.ساختار struct in_addrعضو دیگر sin_addr است که در واقع یک آدرس IPv4 را نشان می دهد. آدرس های IPv4 به صورت ۳۲ بیت مانند 192.168.1.100 یا 127.0.0.1 یا 8.8.8.8 هستند. sin_addr خودش از نوع ساختار دیگر یعنی struct in_addr است. همانگونه که می بینید خود struct in_addr دارای یک عضو به نام s_addr (یا socket address) است که از نوع in_addr_t است و in_addr_t خودش اشاره به نوع uint32_t دارد که یک نوع صحیح بی علامت ۳۲ یبتی است.شکل زیر ساختار struct sockaddr_in را نشان می دهد که در آن سه مولفه اصلی، یعنی sin_family و sin_port و sin_addr به ترتیب ۱ و ۲ و ۸ بایت یا ۸ و ۱۶ و ۳۲ بیت را به خود اختصاص می دهند. ۸ بیت دوم، با شماره مشخص شده ۱ و دو ۸ بیت شماره های ۲ و ۳ و چهار بیت شماره های ۴ تا ۷ به ترتیب برای این عضوها هستند.هر سه این ساختارها در لینوکس در فایل سرآیند intet/in.h شناسانده شده اند.در برنامه نویسی شبکه و سوکت ها، باید متغیری از گونه sockaddr_in بسازیم. یک اشاره گر به struct sockaddr_in را می توان به sockaddr تبدیل (Cast) کرد و وارونه این نیز شدنی است. از این رو در تابعی مانند ()connect که یک ورودی اشاره گر به struct sockaddr می خواهد، می توان اشاره گری از گونه struct sockaddr_in فرستاد.ساختارهای IPv6لینوکس از نسخه ۲.۲ از IPv6 پشتیبانی را آغاز کرده است و از این رو در ارتباط با آن، ساختارهای struct in6_addr و struct sockaddr_in6 فراهم شده اند. در کد زیر می توانید ببینید که یک سوکت IPv6 با ساختار struct sockaddr_in6 نشان داده می شود که همانند سوکت های IPV4 دارای یک نشانی IP و شماره پورت هستند.آدرس فامیلی برای IPv6 همیشه برابر با AF_INET6 خواهد بود.struct scokaddr_in6 - struct in6_addr IPv6در ساختار struct sockaddr_in6 دو عضو به نام های sin6_flowinfo و sin6_scope_id هست که در struct sockaddr_in برای IPv4 نیست. هر آدرس IPv6 دامنه (Scope) ویژه ای دارد که در آن شناسانده شده است. دامنه، یک منطقه توپولوژیکی است که، در آن می توان آدرس IPv6 را به عنوان شناسه ای منحصر (Unique Id) به یک اینترفیس شبکه یا گروهی ای از اینترفیس های شبکه به کار برد. IPv6 از گونه های گوناگونی به نام unicast و multicast و anycast پشتیبانی می کند.گونه Unicast برای آدرس دهی یک تک میزبان (Host)، گونه Multicast برای آدرس دهی یک گروه از میزبان ها و Anycast برای آدرس دهی نزدیکترین عضو یک گروه از هست که بر پایه راهنمای man ip6 در لینوکس پیاده سازی نشده است. شکل زیر این Scope ها و شناسه (ID) آنها را نشان می دهد.IPv6 Scope ID and Nameآموزش IPv6 بسیار گسترده و بیرون از درون مایه این نوشته است و نوشته های جداگانه ای را می خواهد، از این رو IPv6 را دیگر در این سری از آموزش های برنامه نویسی سوکت نخواهم گفت. در نوشته پَسین درباره Address Family و Socket Type ها خواهم گفت.شاد و پیروز و تندرست باشید</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 11 Mar 2020 13:51:55 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش یکم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm</link>
                <description>سوکت مفهومی پایه ای در شبکه ها است که ارتباط میان دو فرایند در دو سوی شبکه (کلاینت - سرور) را فراهم می کند. به طور کلی نیاز است تا دو فرایند یا دو مولفه از فضای کاربر و فضای هسته با یکدیگر ارتباط داشته باشند. این دو فرایند می توانند بر روی یک رایانه و یا بر روی دو رایانه جدا از هم باشند ولی این ارتباط می تواند از راه یک سوکت انجام شود. https://virgool.io/linux-internals/%D8%A2%D8%AF%D8%B1%D8%B3-%D8%AF%D9%87%DB%8C-%D8%AF%D8%B1-%D8%B3%DB%8C%D8%B3%D8%AA%D9%85-%D8%B9%D8%A7%D9%85%D9%84-%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-kg203yzuhgxs در مفاهیم سیستم عامل Inter-Process Communication یا IPC به ارتباط میان دو فرایند اشاره دارد. در سیستم عامل های گوناگون شیوه های گوناگونی برای ارتباط میان دو فرآیند هست که برخی میان سیستم عامل ها همسان و برخی دیگر ویژه همان سیستم عامل هستند. برای نمونه فهرست زیر مکانیزم های شناخته شده و مشهور برای ارتباط میان فرایندها را نشان می دهد:سوکت هافایل های اشتراکیحافظه اشتراکیفایل های Pipe دارای نام و بی نامسیگنال هافرستادن پیغام ها - صفی از پیغام هاسوکت شبکه چیستبرای ارتباط میان دو سوی یک شبکه که به ریخت کلاینت (سرویس گیرنده) و سرور (سرویس دهنده) است، از سوکت شبکه کمک گرفته می شود. سوکت های شبکه بر پایه دو مولفه هستند:  ۱) نشانی IP یا نام دامنه (FQDN) و ۲) شماره درگاه (پورت)هر سرویس دهنده برای نمونه پروتکل های HTTP, DHCP, DNS و یا برنامه های شبکه مانند Telegram, Yahoo Messanger, Skype و یا هر برنامه تحت شبکه ای دیگری دارای یک یا چندین آدرس و یک شماره درگاه هست.شماره درگاه به هر رو، یک شماره یکتا برای آن برنامه است. برای نمونه برای پروتکل HTTP شماره پیش فرض و رِزِرو شده ۸۰ و برای HTTPS شماره ۴۴۳ است ولی می توان شماره درگاه را برای این دو تغییر داد ولی پروتکل دیگری نمی تواند این دو شماره را برای خود ثبت کند. بر فرض اینکه می خواهیم یک برنامه ارتباط میان کارمندان درون شرکت و بر روی شبکه LAN بنویسیم، دو راهکار داریم. نخست آن که اگر برنامه بر پایه پروتکل HTTP باشد، پس شماره درگاه را می توانیم همان ۸۰ یا هر شماره دیگری مانند ۸۰۸۰ یا ۸۰۰۰ یا ۵۰۰۰ یا ۵۰۰۱ به کار ببریم. دوم آن که می توانیم شماره درگاهی دیگر را برگزینیم. به هر رو سوکت دارای دو مولفه زیر است.socket = (IP Aaddress, Port Number)که در آن IP می تواند IPv4 یا IPv6 باشد. در برقراری این ارتباط، کلاینت آغاز کننده ارتباط است و برای برقراری این اربتباط، نیاز به نشانی IP و شماره درگاهی داریم که در سوی دیگر سرور بر روی این دوتایی (IP, Port) به درخواست ها گوش می دهد.ساخت سوکتبرای برقراری ارتباط میان دوی سوی شبکه، نیاز است تا هم در سوی کلاینت و هم در سوی سرور یک سوکت ساخته شود. سوکت ها پلی میان ماشین کلاینت و سرور هستند و آنها را می توان نقطه پایانی (End Point) میان دو سوی شبکه دانست.از دید سوکت های بِرِکلی، تابع هایی که در ادامه فهرست شده اند برای ساخت و به کارگیری سوکت های شبکه در سی استاندارد و همچنین در دیگر زبان های برنامه نوسی مانند سی پلاس پلاس، پایتون، جاوا و دیگر زبان ها به کار می روند.تابع socket برای ساخت و آماده سازی آغازین یک سوکت. این تابع در برنامه نویسی سوی کلاینت و سرور به کار می رود. زیرا در کنار اینکه باید در سرور ورودی برای دریافت درخواست ها باشد، باید در سوی کلاینت نیز ورودی باشد که پاسخ ها را دریافت کند.int sockfd = socket(domain, type, protocol)به طور کلی سوکت یک در (نقطه پایانی) میان سرور و کلاینت است. پلاک این در یک دوتایی است که در سوی کلاینت CLIENT_IP_ADDR:RANDOM_PORT و در سوی سرور SERVER_IP_ADDR:FIXED_PORT است. در سوی کلاینت خود سیستم عامل یک شماره پور تصادفی مانند ۵۶۰۲۵ را به سوکت کلاینت اختصاص می دهد ولی در سوی سرور باید آشکارا یک سوکت را مشخص کنید تا کلاینت از راه آن به سرور وصل شود.در واقع می توانیم بگوییم که نشانی IP همانند کد ملی برای یک ماشین و شماره درگاه همانند شماره پلاک خانه آن ماشین است که این شماره پلاک دستی برای خانه سرور گزینش می شود ولی برای خانه کلاینت خودکار گزنیش خواهد شد. توجه داشته باشید اطلاعات کلاینت IP و PORT در غالب بسته (Packet) به سرور فرستاده می شود، پس سرور با باز کردن این بسته در لایه مربوطه در TCP/IP می فهمد که پاسخ را به چه کسی بفرستد. همچنین در بسته اطلاعات سرور نیز مشخص شده است، پس روترها می فهمند که بسته باید به کدام گیرنده فرستاده شوند.تابع sockoption برای شناساندن گزینه های گوناگون یک سوکتint setsockopt(int sockfd, int level, int optname,  const void *optval, socklen_t optlen);تابع bind برای انقیاد (Binding) دوتایی نشانی IP و شماره درگاه به یک سوکت. به یاد داشته باشید این تابع تنها درون برنامه نویسی سوی سرور به کار می رود.int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);تابع connect برای اتصال کلاینت به سرور به کار می رود. این تابع تنها در برنامه نویسی کلاینت به کارمی رود. قاعدتا کلاینت باید به سرور وصل شود تا درخواست بفرستد.int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);تابع listen برای این است که در سوی سرور، سرور بتواند به درخواست های ورودی گوش دهد. این تابع نیز تنها در برنامه نویسی سرور به کار می رود.int listen(int sockfd, int backlog);تابع accept در سوی سرور برای تایید یک درخواست ورودی به کار می رود.int new_socket= accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);تابع های send و recv که برای فرستادن و دریافت داده ها میان کلاینت و سرور به کار می روند. هر دو تابع در برنامه نویسی سرور و کلاینت می توانند به کار روند.int send(SOCKET socket, const char * buffer, int buflen, int flags);
int recv(SOCKET socket, char * buffer, int buflen, int flags);تابع close در پایان کار یک سوکت را قطع و اصطلاحا آن را می بندد.شکل زیر دید کلی از چگونگی ساخت و رفتار سوکت های شبکه را نشان می دهد. سرآغاز کار با آماده سازی آغازین (Initial) یک سوکت است که به کمک ()socket در هر دو سو انجام می شود. سپس باید در سوی سرور دوتایی های نشانی IP و شماره درگاه به سوکت انقیاد (Bind) شوند که به کمک ()bind انجام می شود. در دنباله در سوی سرو باید ()listen فراخوانی شود تا سرور آماده گوش دادن به درخواست ها شود. در سوی دیگر، یعنی کلاینت نیز یک سوکت با ()socket ساخته شده و اکنون می تواند به کمک ()connect به سرور وصل شود.اکنون که کلاینت به سرور وصل شده، پس درخواست ورودی باید به کمک ()accept تایید شود و در این صورت، از این پس می تواند داده یا اطلاعات را رد و بدل کرد که با ()send و ()recv انجام می شود. در پایان، برای بستن و آزاد سازی سوکت، باید در هر دو سو ()close فراخوانی شود.چرا باید سوکت در پایان آزاد شوددر سیستم عامل های یونیکسی مانند BSD و مکینتاش و شبه یونیکسی مانند لینوکس و سولاریس، همه چیز به ریخت یک فایل است. این فایل می تواند یک فایل متنی ساده، فایل های دودویی مانند فایل های عکس، ویدیو، فایل هایی برای دیوایس ای سخت افزاری که در برگیرنده دو دسته بلاک دیوایس ها مانند هارد دیسک و کاراکتر دیوایس مانند ماوس و کی بورد، فایل های Pipe و همچنین فایل هایی برای سوکت ها می شود.در مفاهیم سیستم عامل، توصیفگر فایل (File Descriptor) شماره ای صحیح و نا منفی است که به یک فایل باز شده اشاره می کند. برای نمونه در هر زبانی مانند سی یا پایتون یا جاوا، در لینوکس فایلی باز شود، برآیند برگشتی یک FD خواهد بود.بنابراین سیستم عامل به هر فایل باز شده و همچنان باز، یک شماره FD اختصاص می دهد که این درباره سوکت ها نیز صدق می کند.  از این رو، تابع ()socket اگر با کامیابی انجام شود، برآیند آن یک شماره int است که همان FD مربوط به سوکت است.int socket_fd;socket_fd = socket(domain, type, protocol)و از همین رو است که باید نام متغیری که به برآیند ()socket اشاره می کند را به تابع ()close بفرستیم تا سوکت آزاد یا قطع شود. همچنین متدهای دیگر، sockopt و bind و listen و connect نیز، ورودی یکم آنها، یک توصیفگر فایل است که به یک سوکت اکنون باز اشاره می کند.آنچه که گفته شد پیشگفتاری بر سوکت های بِرِکلی در سی و لینوکس است که برای پیاده سازی یک برنمه سرور-کلاینت ساده، باید یک سری دیگر از ریزه کاری ها در نوشته هایی دیگر گفته شود. بنابراین دنباله نوشته برای آینده.شاد و تندرست و پیروز باشید.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Tue, 10 Mar 2020 16:24:28 +0330</pubDate>
            </item>
                    <item>
                <title>فایل های راه انداز در Bash</title>
                <link>https://virgool.io/linux-internals/%D9%81%D8%A7%DB%8C%D9%84-%D9%87%D8%A7%DB%8C-%D8%B1%D8%A7%D9%87-%D8%A7%D9%86%D8%AF%D8%A7%D8%B2-%D8%AF%D8%B1-bash-nruf1e7adzbz</link>
                <description>هر کدام از پوسته های لینوکسی دارای یک سری از فایل ها هستند که به آنها فایل های راه انداز یا Startup File گفته می شود، زیرا پس از بار گذاری و بالا آمدن لینوکس و در هنگام راه اندازی لینوکس و ورود (Login) به سیستم این فایل ها خوانده می شوند. فایل های راه انداز به ازای هر کاربر و در زیر دایرکتوری خانگی آن قرار دارند.در توزیع های لینوکسی سه فایل در دایرکتوری خانگی کاربر هستند که هر سه پنهان شده اند.  این فایل ها، bashrc و bash_profile و bash_history نام دارند. دستور زیر فهرست همه فایل های پنهانی را در زیر دایرکتوری خانگی نشان می دهد که نام آنها با رشته bash. آغاز می شود. شکل زیر خروجی دستور را نشان می دهد. البته توزیع های لینوکسی فایل دیگری به نام etc/profile/ نیز هست که جز فایل های راه انداز پوسته Bash هستند. البته در خروجی زیر، فایلی به نام bash_history. هست که آن جز فایل های را انداز نیست. پس چهار  فایل زیر (همراه etc/profile/) شماری از فایل های راه انداز پوسته bash هستند.ls -ld $HOME/.bash*$HOME/.bashrc$HOME/.bash_profile$HOME/.bash_logoutetc/profiles/متغیر HOME$ یکی از متغیرهای محیطی است که پیش فرض پس از نصب لینوکس، ساخته می شود و مسیر دایرکتوری خانگی کاربر کنونی که به سیستم وارد شده است را نگه می دارد.فایل bashrc. در زیر دایرکتوری خانگیاین فایل معمولا برای شناساندن (تعریف) متغیرهای محیطی به کار گرفته می شوند که این متغیرها بدست برخی از برنامه ها مانند جاوا، برنامه های نوشته شده به زبان جاوا و همچنین اوراکل به کار گرفته می شوند. برای نمونه برخی از برنامه های نوشته شده به زبان جاوا، نیاز دارند تا مسیر نصب جاوا را از متغیری به نام JAVA_HOME$ بخوانند. همچنین در پیوند زیر، نشان دادیم که چگونه باید محیط نصب اوراکل، را آماده کنید که در برگیرنده ساخت و شناساندن برخی از متغیرها است.همچنین این فایل رفتار پوسته Interactive را مشخص می کند برای همین برخی پیشنهاد می کنند که متغیرهای محیطی دلخواه و شناسانده شده به دست خودمان را در فایل دیگر، یعنی HOME/.bash_profile$ بنویسیم. فایل bashrc. در برگیرنده کدهای شل اسکریپتی است که خواندن و فهم آنها، نخست به شما کمک می کند که بیشتر با اسکریپت نویسی پوسته آشنا شوید و همچنین کمک می کند درک بهتری از پوسته bash داشته باشید.فایل bash_profile. در زیر دایرکتوری خانگیشاید این فایل در توزیع لینوکسی شما نباشد و تنها فایل HOME/.bashrc باشد. برای نمونه در سیستم عامل مکینتاش فایل HOME/.bashrc$ نیست و تنها فایل HOME/.bash_profile$ هست ولی در توزیع ابونتو 18.04LTS تنها فایل HOME/.bashrc$ هست. در این فایل نیز می توان متغیرها و نام های مستعار یا توابع و دیگر پیکربندی های bash را بنویسیم.فایل bash_logout. در زیر دایرکتوری خانگیهمانگونه که از نامش، این فایل در زمان بیرون رفتن (Logout) از سیستم خوانده و پردازش می شود، بنابراین می توانیم دستورها یا اسکریپت هایی را درون آن بنویسیم که می خواهیم آنها در زمان بیرون رفتن از سیستم انجام (اجرا) شوند. برای نمونه در این فایل می تواند دستور clear_console باشد که نخست صفحه نمایش را پاک می کند و سپس شما از حساب کاربری تان بیرون می روید. شکل زیر نشان می دهد که دستور clear_console برای پاک کردن کنسول پیش از بیرون رفتن از حساب کاربری، انجام می شود.توجه کنید در بیشتر سازمان ها و محیط هایی که لینوکس را به کار می برند، لینوکس فاقد واسط کاربری GUI مانند Gnome و KDE است. همچنین کاربران با SSH و از راه دور و به سرور وصل می شوند که دیگر هیچ میزکاری در این ارتباط راه دور در کار نیست و همه به گونه خط فرمان است.کاربرد و تفاوت میان bashrc با bash_profile و bash_logoutتوجه کنید که دست کم یکی از این دو فایل در زیر دایرکتوری خانگی همه کاربران هست و هر دو پنهان شده اند، زیرا آغاز نام آنها یک نقطه گذاشته شده است. فایل HOME/.bash_profile تنها زمانی خوانده و پردازش و تفسیر می شود که از یک Interactive Login Shell به سیستم وارد شویم ولی هر زمان که یک پوسته bash فراخوانی شود، فایل HOME/.bashrc خوانده می شود. بنابراین فایل HOME/.bash_profile در زمان ورود به سیستم خوانده می شود، پس می توانیم دستورها یا اسکریپت هایی را در آن مشخص کنیم، تا آنها در زمان ورود به سیستم، انجام (اجرا) شوند.فایل HOME/.bash_profile$ در زمان ورود (Login) به سیستم از یک Login Shell خوانده وتفسیر می شود.فایل HOME/.bash_logout$ در زمان بیرون رفتن (Logout) از سیستم خوانده و تفسیر می شود.فایل HOME/.bashrc$ هر زمان که یک پوسته bash فراخوانی شود، خوانده و پردازش می شود. هر گاه که یک پنجره گرافیکی برنامه ترمینال در میزکاری مانند گنوم را باز می کنیم، پس یک پوسته bash فراخوانی می شود.در هر دو فایل HOME/.bash_profile$ و HOME/.bashrc$ می توانید متغیرها، نام های مستعار و توابع خود را تعریف کنید ولی بستگی دارد که کدام یک در دایرکتوری خانگی شما هست.اگر یکی از این دو فایل نباشد، نگران نباشید، می توانید آن را دستی بسازید. پوسته bash با نبود یکی از آنها ایرادی نمی گیرد ولی باید قابل خوانده شده (دارای مجوز read) باشند.فایل etc/profile/دو فایل HOME/.bashrc$ و HOME/.bash_profile$ هر دو پیکربندی هایی را برای یک کاربر نگهداری می کنند ولی دسته دیگری از فایل های راه انداز Bash (یا هر پوسته دیگری) هستند که به گونه سراسری پیکربندی ها را در خود نگه می دارند. دوتای این فایل ها، etc/profile/ و etc/bashrc/ نام دارند.توجه کنید که فایل های راه انداز پیکربندی هایی را برای محیط لینوکس نگه داری می کنند که می توانند به گونه سراسری یا به گونه به ازای هر کاربر باشند.شکل زیر نمونه ای از محتوای فایل را در توزیع لینوکسی ابوتنو ۱۸.۰۴ نشان می دهد که تنها بخشی از آن را برای بازگویی کاربرد این فایل نمایان کرده ایم. در بخش قرمز رنگ، بررسی می شود که آیا شناسه کاربری که به سیستم وارد شده است، برابر با شماره صفر است یا نه؟ اگر باشد، پس کاربر root است، پس باید کاراکتر # در خط اعلان درون خط فرمان نشان داده شود. ولی اگر کاربری جز root باشد، پس شناسه کاربری آن صفر نیست، پس باید کاراکتر $ برای آن نشان داده شود.تنها کاربر root در لینوکس (ودیگر سیستم عامل های یونیکسی) است که شناسه کاربری یا User Id آن برابر شماره صفر است.زمانی که کاربری ساده (root نباشد) به سیستم وارد می شود، خط فرمانی را باز کند، پیش روی خط اعلان (یا Command Prompt) آن کاراکتر $ گذاشته می شود.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 05 Jul 2019 12:18:54 +0430</pubDate>
            </item>
                    <item>
                <title>مفهوم Shell یا پوسته در لینوکس</title>
                <link>https://virgool.io/linux-internals/%D9%85%D9%81%D9%87%D9%88%D9%85-shell-%DB%8C%D8%A7-%D9%BE%D9%88%D8%B3%D8%AA%D9%87-%D8%AF%D8%B1-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-ggq8yq6egsua</link>
                <description>پوشه (Shell) در همه سیستم عامل ها لایه ای میان کاربر و هسته سیستم عامل است. پوسته ها را بیشتر به گونه خط فرمان (Command Line) می شناسیم که دستورهایی را از کاربر گرفته و سپس یک خروجی را برگشت می دهند. این خروجی می تواند یک خطا یا یک مقدار درست و دلخواه شما باشد. بنابراین پوسته ها یک ورودی را دریافت و سپس خروجی را برگشت می دهند.توجه کنید که نباید مفهوم پوسته و ترمینال را با یکدیگر یکسان بدانید. پوسته یک لایه از سیستم عامل است که می توانیم آن را یک مفسر دستورهای ورودی از سوی کاربر است ولی ترمینال (Terminal) یک نرم افزار است که وظیفه آن دریافت دستور است ولی کاربرد پوسته، تفسیر و اجرای دستورهایی است که از ترمینال فرستاده شده اند. در زیر نام برخی از پوسته های مشهور در سیستم عامل های یونیکسی فهرست شده است.BashZShCShKornدر سیستم عامل های یونیکسی مانند لینوکس، مکینتاش، سولاریس و FreeBSD، یک پوسته مانند Bash یا Korn یک مفسر (interpreter) و یک زبان برنامه نویسی است. از دید مفسر، گفتیم که پوسته باید واسطه ای یا لایه میان کاربر با سیستم عامل برای انجام دستورهای کاربر است که می توانیم به ساخت یک فایل یا دایرکتوری و یا تغییر به دایرکتوری دیگر و دیگر نمونه اشاره کنیم.آنچه که در نوشته های اسکریپت نویسی پوسته (Shell Scripting) در لینوکس (یا بهتر است بگوییم در یونیکس) خواهیم گفت، همین جنبه برنامه نویسی پوسته ها است. برنامه نویسی یا اسکریپت نویسی پوسته، ترکیب از ویژگی های زبان های برنامه نویسی و دستورهای درون توزیع لینوکس است. بهتر است بگوییم که اسکریپت نویسی شل یا پوسته، امکان خودکار سازی انجام چندین و چند دستور را فراهم می کند به گونه ای که می توانیم خروجی یک دستور درون یک متغیر دخیره کرده و سپس متغیر را در دستور دیگری به کار ببریم. می توانیم با با دستور if عبارت های شرطی را پیاده سازی کنیم یا اینکه می توانیم از حلقه تکرار کمک بگیریم.از دید انجام (یا اجرای) دستورها، پوسته ها می توانند به دو گونه پوسته های هم کنشی (یا تعاملی – Interactively) و نا هم کنشی (غیر تعاملی – Non Interactively) باشند. در پوسته های interactively، یک دستور از صفحه کلید به پوسته فرستاده می شود ولی در پوسته های Non Interactively، دستور یا دستورها از یک فایل به پوسته ها فرستاده خواهند شد.در اسکریپت نویسی پوسته نیز دستورها با ترکیب قابلیت های برنامه نویسی درون یک فایل نوشته شده و سپس این فایل از طریق یک ترمینال یا حتی از درون دیگر زبان های برنامه نویسی انجام (اجرا) می شود. از دید خودکار سازی انجام دستورها، اگر اسکریپت نویسی پوسته نباشد، پس باید تک تک، هر کدام از دستورها را برای کاربرد دلخواه، پشت سر هم انجام دهیم ولی با اسکریپت نویسی پوسته، همگی در کنار قابلیت های برنامه نویسی درون فایل نوشته شده و سپس این فایل را اجرا می کنیم.از دید دیگری درباره انجام دستورها، دستورها می توانند به گونه همگام (Synchronously) یا ناهمگام (Asynchronously) انجام شوند. در دستورهایی که همگام انجام می شوند، پوسته قفل شده و تا زمانی که دستور کنونی پایان نیابد، پوسته برای انجام دستور دیگر، آزاد نمی شود. ولی در حالت ناهمگام، پوسته منتظر پایان یافتن دستور دیگری نمی شود، بلکه دستور کنونی را در پس زمینه اجرا کرده و سپس دستور دیگری را دریافت می کند. هر زمان که خروجی دستور پس زمینه آماده شد، آنرا نمایش می دهد.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Thu, 04 Jul 2019 17:22:52 +0430</pubDate>
            </item>
                    <item>
                <title>آدرس دهی در سیستم عامل ها - بخش یکم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%AF%D8%B1%D8%B3-%D8%AF%D9%87%DB%8C-%D8%AF%D8%B1-%D8%B3%DB%8C%D8%B3%D8%AA%D9%85-%D8%B9%D8%A7%D9%85%D9%84-%D9%87%D8%A7-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-kg203yzuhgxs</link>
                <description>برای آغاز آموزش های هسته لینوکس، بهتر است پرداختن به پردازش ها، زمانبدی، اولویت پردازش ها، برنامه نویسی شبکه و مولفه های شبکه و بسیاری دیگر از جنبه های سیستم عامل، نخست مفهوم آدرس دهی را بدانیم.بدون نکه وارد گونه های حافظه بشویم، یکباره در مورد RAM سخن می گوییم. RAM حافظه اصلی (Main Memory) است، زیرا در هم کنش (تعامل) سر راست با پردازنده است. هر فرایندی که می خواهد اجرا شود، یا بهتر بگویم، هر فرایندی که پردازنده می خواهد، نخست باید درون حافظه بنشیند.از دید چرخه زندگی (Life Cycle) یک فرایند، فرایندهای که درون حافظه اصلی هستند در حالت آماده (Ready) و فرایندهای که پردازنده دارند در حالت اجرا (Running) هستند. بنابراین گام نخست برای اجرا شدن فرایند، نشستن فرایند در حافظه اصلی است.از دید برنامه نویس ها، آدرس حافظه یک سلول است که محتوایی (مانند مقدار یک متغیر) درون آن نگهداری می شود. این سلول های فضای آدرس، به گونه یک پشته، از پایین به بالا با یک شماره هگزا دسیمال (مبنای ۱۶) آدرس دهی شده اند.اما از یک دید فضای آدرس به دو بخش Kernel Space و User Space تقسیم می شود. هسته سیستم عامل و همه مولفه های آن مانند راه اندازه های سخت افزار یا همان درایورها، سیستم فایل، پشته شبکه و همه دیگر مولفه های هسته درون فضای هسته نگهداری می شوند. شکل زیر گویای همه چیز است و در دنباله با این شکل، مفهوم Kernel Space و User Space را آموزش می دهم.نمایی از دو فضای User و Kernelفضای کاربر، شامل همه کدهایی درون سیستم عامل می شود که خارج از هسته هستند. برای نمونه خواندن از یک فایل روی سیستم فایل. دستورهای خط فرمان و برنامه های گرافیکی، همگی درون فضای User از حافظه اصلی نگهداری می شوند.هیچ کدام از فرایندهایی که درون فضای کاربر هستند، نمی توانند به فضای هسته و کدها و مولفه های آن دسترسی داشته باشند. بنابراین فضای هسته از دسترس فرایندهای کاربر، محافظت می شود. برای برقراری ارتباط میان برنامه فضای کاربر با فضای هسته، مکانیزمی به نام فراخوان سیستمی (System Call) وجود دارد. هرسیستم فایل دارای یک شماره یکتا و دارای یک کاربرد ویژه است.برای نمونه فراخوان سیستمی open برای دسترسی به سیستم فایل و دسترسی به بلاک های آن به کار می رود. بنابراین در توابعی مانند ()open از زبان سی، این تابع است که شما را به فراخوان سیستمی open ارتباط داده و خود فراخوان سیستمی است که با هسته و در اینجا با سیستم فایل در ارتباط است.در شکل بالا فرض کنید پوسته (Shell) لینوکس، bash را باز کردید، پس خود آن از این پس یک فرایند است و باید درون فضای آدرس بخش User Space قرار بگیرد. همچنین در همه سیستم عامل ها، هر فرایند دارای یک شناسه یکتا به نام PID (یا Process ID) است. پس برنامه یا بهتر بگوییم فرایند، شناسه خود را از هسته می گیرد.در مورد دیگر، می خواهیم بوسیله دستور cat فایل etc/host/ را بخوانیم، پس درون کدهای دستور cat از تابع ()open در زبان سی کمک گرفته شده تا با فراخوان سیستمی open ارتباط پیدا کرده و سپس نخست با مولفه VFS  (یا Virtual File System) ارتباط برقرار کند و بوسیله VFS است که با سیستم فایل مربوطه (در اینجا XFS) ارتباط برقرار می شود. خود سیستم فایل یاه بهتر بگوییم، کدهای سیستم فایل نیز می دانند چگونه باید به بلاک های مورد نظر روی دیسک برای نمایش محتوای فایل دسترسی پیدا کنند.در نوشته های آینده مفاهیم آدرس دهی حافظه، فرایند و سیستم فایل را بیشتر آموزش می دهیم. آموزش خواهیم داد که آدرس دهی حافظه به سه گونه Logical Address و  Virtual Address و Physical Adress دسته بندی می شوند.منبع شکل</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Sun, 05 May 2019 22:06:57 +0430</pubDate>
            </item>
                    <item>
                <title>معماری سیستم کامپیوتر بر پایه پردازنده ها</title>
                <link>https://virgool.io/linux-internals/%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D8%B3%DB%8C%D8%B3%D8%AA%D9%85-%DA%A9%D8%A7%D9%85%D9%BE%DB%8C%D9%88%D8%AA%D8%B1-%D8%A8%D8%B1-%D9%BE%D8%A7%DB%8C%D9%87-%D9%BE%D8%B1%D8%AF%D8%A7%D8%B2%D9%86%D8%AF%D9%87-%D9%87%D8%A7-ynbrak5re5wx</link>
                <description>سیستم های کامپیوتریبر پایه پردازنده ها می توانند شامل تک پردازنده (Single Processor) یا چندین (Multi Processors) باشند. در تک پردازنده ای، پردازنده با سوئیچ کردن پردازنده میان پردازش ها، اجازه می دهد تا پردازنده میان چندین پردازش به اشتراک گذاشته شود. سرعت سوئیچ پردازنده به اندازه ای بالا است که کاربر از آن آگاه نیست. به این گونه، همروندی می گویند.همروندی به این مفهوم است که یک پردازنده بتواند چندین پردازش را اجرا کند. هسته سیستم عامل الگوریتمی را برای این منظور به کار می برد. الگوریتم های گوناگونی برای اجرا پردازش ها و سوئیچ کردن آنها میان پردازنده هست که هر کدام از سیستم عامل ها، الگوریتم خودش را به کار می برد.در چند پردازنده ای می توان به گونه موازی چندین پردازش را اجرا کرد. پردازش موازی سرعت اجرا را بالا می برد. برای زمینه هایی محاسباتی بالا مانند ماتریس ها یاپردازش داده ها، سیستم چند پردازنده ای کارآمد خواهد بود. همه کار بر روی پردازنده های گوناگون پخش شده و سپس پاسخ پایانی از گردآوری همه پاسخ ها، بدست می آید.در تک پردازنده ای همه حافظه در اختیار همان تک پردازنده است ولی در چند پردازنده ای حافظه یا به گونه اشتراکی میان همه پردازنده ها و یا به شیوه خصوصی برای هر کدام از پردازنده ها است. سیستم چند پردازنده ای که حافظه میان تمامی پردازنده ها اشتراکی است را، چند پردازنده ای متفارن (Symmetric Multi Processing یا SMP) می گویند و سیستم چند پردازنده ای که هر کدام از پردازنده ها حافظه خصوصی خودشان را دارند را سیستم های چند پردازنده ای نامتقاران (Asymmetric Multi Processing یا AMP) می گویند.معماری AMP (نامتقارن) به گونه Master-Slave است به گونه ای که به هر کدام از پردازنده ها، یک وظیفه (Task) ویژه انتساب داده می شود. تنها یک پردازنده Master و دیگران Slave هستند. سیستم عامل بر روی پردازنده Master و دیگر فرایندها بر روی پردازنده های Slave اجرا می شوند. در معماری SMP دیگر پردازش های Master و Slave نیست و همه پردازنده ها، همه گونه فرایندهای درون سیستم عامل را اجرا می کنند.۱ - در AMP یک پردازنده تمامی فرایندهای خود سیستم عامل را اجرا می کند.۲ - در AMP پردازنده Master وظیفه واگذاری فرایند را به هر کدام از پردازنده های Slave دارد و یا اینکه از پیش یک فرایند به Slave واگذار شده است.۳ - در SMP یک صف فرایندهای آماده اجرا است یا اینکه هر کدام از فرایندها صف اجرای خصوصی خودش را دارد.۴ - در AMP اگر Master از کار بی افتد، یکی از Slave ها جایگزین و از این پس Slave شناخته می شود. اگر Slave از کار بی افتد،فرایندهای آن به دیگری سوئیچ می شود.۵ - در SMP با از کار افتادن یکی از پردازنده ها، کارایی سیستم کاهش پیدا می کند.۶ - در SMP تمامی پردازنده بوسیله حافظه اشتراکی (Shared Memory) با هم ارتباط بر قرار می کنند.۷ - در AMP پردازنده های Slave از Matsre برای ارتباط با یکدیگر کمک می گیرند.</description>
                <category>مفاهیم سیستم عامل</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 03 May 2019 21:27:53 +0430</pubDate>
            </item>
            </channel>
</rss>