Amin'sTechLab
Open in Telegram
🔬 Embedded Systems | AI | FPGA | PCB Design 🚀 Exploring tech at the edge of innovation 🧠 Founder of AminTechLab 📍Engineering the future – one bit at a time
Show more1 962
Subscribers
+224 hours
+87 days
+630 days
Posts Archive
1 962
🔥 قسمت ۳: فعالسازی حالت Performance برای CPU در لینوکس
بعد از نصب cpupower، میتوانید با یک دستور ساده CPU را روی حالت حداکثر عملکرد قرار دهید:
sudo cpupower frequency-set -g performance
با اجرای این دستور، Governor پردازنده روی حالت performance تنظیم میشود.
در این حالت، سیستم تلاش میکند پردازنده را در سطح بالاتری از توان پردازشی نگه دارد تا برنامهها سریعتر پاسخ دهند و پردازشهای سنگین با تأخیر کمتری انجام شوند.
این حالت برای موقعیتهایی مثل موارد زیر مناسب است:
کامپایل پروژههای سنگین
رندر گرفتن
اجرای ماشین مجازی
پردازش داده
اجرای بازی
تست و بنچمارک سیستم
اجرای سرویسهای حساس به تأخیر
اما حالت performance همیشه بهترین انتخاب نیست.
اگر از لپتاپ استفاده میکنید، فعال بودن دائمی این حالت میتواند باعث افزایش مصرف باتری، بالا رفتن دمای CPU و بیشتر شدن صدای فن شود.
برای برگشت به حالت کممصرفتر میتوانید از دستور زیر استفاده کنید:
sudo cpupower frequency-set -g powersave
اگر سیستم شما از schedutil پشتیبانی میکند، این حالت معمولاً انتخاب متعادلی بین عملکرد و مصرف انرژی است:
sudo cpupower frequency-set -g schedutil
جمعبندی ساده:
performance یعنی قدرت بیشتر، مصرف بیشتر و دمای بالاتر.
powersave یعنی مصرف کمتر، عملکرد محدودتر و شارژدهی بهتر.
schedutil یا ondemand یعنی تعادل بین سرعت و مصرف انرژی.
پس اگر به حداکثر توان CPU نیاز دارید، performance گزینه مناسبی است؛ اما برای استفاده روزمره، حالتهای متعادل معمولاً انتخاب بهتری هستند.
@Amin_TechLab
1 962
⚙️ قسمت ۲: نصب و بررسی وضعیت CPU با
cpupower
برای استفاده از ابزار cpupower ابتدا باید بسته مربوط به آن را نصب کنید. نام بسته در توزیعهای مختلف لینوکس ممکن است متفاوت باشد.
📦 در اوبونتو، دبیان و توزیعهای مبتنی بر آنها:
sudo apt update
sudo apt install linux-tools-common
در بعضی نسخههای اوبونتو ممکن است لازم باشد ابزار مخصوص کرنل فعلی را هم نصب کنید:
sudo apt install linux-tools-$(uname -r)
📦 در فدورا:
sudo dnf install kernel-tools
📦 در Red Hat / RHEL / CentOS:
sudo yum install kernel-tools
یا در نسخههای جدیدتر:
sudo dnf install kernel-tools
📦 در آرچ لینوکس و توزیعهای مبتنی بر آن:
sudo pacman -S cpupower
بعد از نصب، بهتر است قبل از تغییر تنظیمات، وضعیت فعلی پردازنده را بررسی کنید:
cpupower frequency-infoاین دستور اطلاعات مهمی درباره CPU نمایش میدهد؛ از جمله: حداقل و حداکثر فرکانس پردازنده Governor فعال فعلی درایور مدیریت فرکانس CPU حالتهای قابل استفاده برای مدیریت مصرف انرژی محدوده فرکانسی قابل پشتیبانی توسط پردازنده در خروجی این دستور معمولاً بخشی با عنوان available cpufreq governors وجود دارد. این بخش نشان میدهد سیستم شما از چه حالتهایی مثل
performance، powersave، ondemand یا schedutil پشتیبانی میکند.
بررسی این اطلاعات قبل از اعمال تغییرات مهم است، چون همه سیستمها دقیقاً گزینههای یکسانی ندارند.
ادامه دارد...
@Amin_TechLab1 962
تا امروز خیلی از ما از ابزارهای AI مثل Claude Code، Cursor یا Codex بیشتر شبیه یک چتبات استفاده میکردیم.
یک Prompt مینوشتیم، خروجی میگرفتیم، ایرادها را اصلاح میکردیم و دوباره Prompt جدید میدادیم.
اما بهنظر میرسد قدم بعدی برای برنامهنویسها، چیزی فراتر از Prompt Engineering باشد:
🔥 Loop Engineering
در این رویکرد، تمرکز فقط روی نوشتن Prompt بهتر نیست؛ بلکه روی طراحی یک چرخه کاری هوشمند است.
یعنی بهجای اینکه همیشه انسان مرحلهبهمرحله به AI بگوید چه کاری انجام دهد، یک سیستم طراحی میشود که Agentها بتوانند داخل آن کار را جلو ببرند.
مثلاً Agent میتواند:
🔹 تسکها را بررسی کند
🔹 کد را تغییر دهد
🔹 تستها را اجرا کند
🔹 خطاها را پیدا و اصلاح کند
🔹 Pull Requestها را بررسی کند
🔹 Issueها را مدیریت کند
🔹 Changelog بسازد
🔹 و فقط وقتی تصمیم انسانی لازم بود، کار را به انسان ارجاع دهد
به زبان ساده، مسیر در حال تغییر است:
از این مدل:
«من Prompt مینویسم، AI جواب میدهد»
به این مدل:
«من سیستم را طراحی میکنم، Agentها داخل آن سیستم کار را جلو میبرند.»
این تغییر برای تیمهای نرمافزاری خیلی مهم اس
1 962
🚀 قسمت ۱: افزایش عملکرد CPU در لینوکس با
cpupower
اگر از لینوکس استفاده میکنید و میخواهید در کارهای سنگین، عملکرد پردازنده را افزایش دهید، یکی از ابزارهای کاربردی برای این کار cpupower است.
این ابزار به شما اجازه میدهد حالت کاری CPU را تغییر دهید و مشخص کنید پردازنده بیشتر روی مصرف انرژی تمرکز کند یا روی حداکثر عملکرد.
در لینوکس، CPU همیشه با یک فرکانس ثابت کار نمیکند. سیستمعامل با توجه به میزان فشار کاری، دما، مصرف برق و تنظیمات مدیریت انرژی، فرکانس پردازنده را کم یا زیاد میکند.
این رفتار توسط چیزی به نام CPU Governor کنترل میشود.
Governor در واقع سیاست کاری پردازنده را مشخص میکند.
برای مثال:
powersave
مصرف انرژی را کاهش میدهد و معمولاً CPU را در فرکانس پایینتری نگه میدارد.
ondemand
فرکانس پردازنده را با توجه به نیاز سیستم کم و زیاد میکند.
schedutil
در سیستمهای جدیدتر رایج است و تلاش میکند بین مصرف انرژی و عملکرد تعادل ایجاد کند.
performance
پردازنده را در حالت حداکثر عملکرد قرار میدهد.
اگر در حال کامپایل پروژههای بزرگ، اجرای ماشین مجازی، بازی، رندر، پردازش داده یا بنچمارک هستید، حالت performance میتواند باعث افزایش سرعت پاسخدهی سیستم شود.
اما باید توجه داشت که این حالت معمولاً مصرف انرژی و دمای CPU را هم افزایش میدهد.
پس اگر از لپتاپ استفاده میکنید، بهتر است فقط زمانی که واقعاً به قدرت پردازشی بالا نیاز دارید، این حالت را فعال کنید.
ادامه دارد...
@Amin_TechLab1 962
🐍 سه نقطه
... در پایتون فقط برای زیبایی نیست!
شاید در بعضی از کدهای پایتون چیزی شبیه این دیده باشید:
def process_data():
...
در نگاه اول ممکن است فکر کنیم این سه نقطه فقط برای خالی گذاشتن بدنه تابع استفاده شده یا چیزی شبیه pass است؛ اما در پایتون، ... یک مفهوم واقعی دارد.
در واقع ... همان آبجکتی به نام Ellipsis است.
>>> ... Ellipsis >>> type(...) <class 'ellipsis'>یعنی سه نقطه در پایتون نه کامنت است، نه صرفاً یک علامت نمایشی، بلکه یک آبجکت واقعی از نوع
ellipsis محسوب میشود.
اما سؤال اصلی اینجاست:
آیا ... همان pass است؟
نه دقیقاً.
pass یک statement خالی است. یعنی وقتی پایتون به آن میرسد، هیچ کاری انجام نمیدهد و فقط اجازه میدهد ساختار کد از نظر نحوی معتبر باقی بماند.
مثلاً:
def process_data():
pass
اینجا pass فقط میگوید:
«فعلاً این بخش خالی است، ولی از نظر syntax مشکلی ندارد.»
اما ... یک expression است، یعنی خودش یک مقدار واقعی تولید میکند:
x = ... print(x)خروجی:
Ellipsisپس تفاوت مهم اینجاست:
passهیچ مقداری تولید نمیکند. ولی:
...یک آبجکت واقعی به نام
Ellipsis است.
یکی از کاربردهای رایج ... این است که در زمان طراحی اولیه کد، جای بخشهایی را که هنوز پیادهسازی نشدهاند نگه داریم:
class UserService:
def create_user(self):
...
def delete_user(self):
...
این روش بهخصوص در نوشتن اسکلت اولیه کلاسها، توابع، اینترفیسها یا کدهایی که قرار است بعداً تکمیل شوند، کاربرد دارد.
البته از نظر خوانایی، اگر فقط میخواهید بگویید «اینجا هنوز کاری انجام نمیشود»، استفاده از pass همچنان رایجتر و واضحتر است.
اما Ellipsis فقط برای خالی گذاشتن تابع نیست. در بعضی کتابخانهها، مخصوصاً در حوزههایی مثل NumPy، از ... برای indexing و slicing پیشرفته استفاده میشود.
مثلاً:
array[..., 0]در اینجا
... معنای خاصی دارد و به کتابخانه کمک میکند با ابعاد مختلف آرایهها راحتتر کار کند.
همچنین در type hinting و stub fileها هم زیاد دیده میشود؛ مخصوصاً در فایلهایی که فقط ساختار تابع یا کلاس را مشخص میکنند، اما پیادهسازی واقعی ندارند.
مثلاً:
def connect(host: str, port: int) -> bool: ...
در این حالت، ... یعنی امضای تابع مشخص شده، اما بدنه آن در جای دیگری تعریف میشود یا فعلاً اهمیتی ندارد.
پس دفعه بعد که در کد پایتون با ... روبهرو شدید، بدانید که این سه نقطه فقط یک جایخالی ساده نیست.
... در پایتون همان Ellipsis است؛ یک آبجکت واقعی، با کاربردهایی فراتر از چیزی که در نگاه اول به نظر میرسد.
@Amin_TechLab1 962
💻 یکی از خطرناکترین مفاهیم در زبان C: Undefined Behavior
در زبان C، همیشه اینطور نیست که هر کدی که کامپایل میشود، الزاماً رفتار مشخص و قابل اعتمادی داشته باشد.
گاهی برنامه از نظر ظاهری درست به نظر میرسد، کامپایلر هم هیچ خطایی نمیدهد، اما نتیجه اجرای برنامه میتواند کاملاً غیرقابل پیشبینی باشد.
به این حالت در زبان C میگوییم:
Undefined Behavior
یا به اختصار: UB
یعنی استاندارد زبان C هیچ تضمینی نمیدهد که برنامه دقیقاً چه رفتاری داشته باشد.
برای مثال به این کد دقت کنید:
#include <stdio.h>
int main() {
int x = 5;
int y = x++ + ++x;
printf("%d\n", y);
return 0;
}
شاید در نگاه اول فکر کنیم مقدار y قابل محاسبه است.
اما مشکل اینجاست که در این عبارت، متغیر x بیش از یک بار بین دو نقطهی مشخص از اجرای برنامه تغییر کرده است و ترتیب دقیق این تغییرات تضمینشده نیست.
نتیجه؟
ممکن است در یک کامپایلر عددی چاپ شود، در کامپایلر دیگر عددی متفاوت، و حتی با تغییر سطح optimization نتیجه عوض شود.
مثلاً اجرای برنامه با:
gcc main.cممکن است یک خروجی بدهد، اما با:
gcc main.c -O2خروجی متفاوتی ببینیم. این یعنی برنامه وارد محدودهی Undefined Behavior شده است. یک نمونه معروفتر:
int arr[3] = {1, 2, 3};
printf("%d\n", arr[5]);
اینجا ما در حال دسترسی به خانهای خارج از محدودهی آرایه هستیم.
زبان C جلوی ما را نمیگیرد، اما این به معنی درست بودن کد نیست.
ممکن است برنامه اجرا شود، ممکن است مقدار بیمعنی چاپ کند، ممکن است crash کند، یا حتی ظاهراً بدون مشکل کار کند.
و همین «ظاهراً بدون مشکل کار کردن» خطرناکترین بخش ماجراست.
در زبانهایی مثل Python یا Java معمولاً چنین خطاهایی سریعتر و واضحتر مشخص میشوند، اما در C مسئولیت زیادی روی دوش برنامهنویس است.
برای جلوگیری از Undefined Behavior بهتر است:
int x = 5;
x++;
int y = x;
x++;
y += x;
بهجای نوشتن عبارتهای پیچیده، تغییرات را مرحلهبهمرحله و خوانا بنویسیم.
زبان C بسیار سریع، قدرتمند و نزدیک به سختافزار است؛ اما همین قدرت باعث میشود کوچکترین بیدقتی، رفتار برنامه را غیرقابل پیشبینی کند.
پس در C فقط کامپایل شدن کد کافی نیست؛
باید مطمئن باشیم کد از نظر استاندارد زبان هم رفتار مشخصی دارد. ⚠️
@Amin_TechLab1 962
💻 آشنایی با چند اپراتور کمتر شناختهشده در زبان C
در زبان C، مقادیری که روی آنها عملیات انجام میشود را Operand و نماد انجامدهنده عملیات را Operator مینامیم.
برای مثال در کد زیر:
if (x > y) {
...
}
متغیرهای x و y نقش Operand را دارند و علامت > یک Operator است.
اما در میان اپراتورهای زبان C، چند مورد وجود دارد که شاید کمتر به آنها توجه کرده باشید.
یکی از آنها Comma Operator یا همان اپراتور ویرگول است.
در زبان C، ویرگول همیشه فقط برای جدا کردن آرگومانها یا متغیرها نیست؛ گاهی خودش یک اپراتور واقعی است.
این اپراتور چند عبارت را از چپ به راست اجرا میکند، اما مقدار نهایی آن برابر با مقدار آخرین عبارت است.
مثلاً:
int x;
x = (printf("Hello\n"), 10);
در این کد، ابتدا دستور printf اجرا میشود و سپس مقدار 10 داخل متغیر x قرار میگیرد.
یعنی بعد از اجرای کد بالا، مقدار x برابر با 10 خواهد بود.
یک نمونه کاربردیتر:
int i = 0;
int j = 0;
while (i < 5)
j += i, i++;
در اینجا ابتدا مقدار i به j اضافه میشود و سپس i یک واحد افزایش پیدا میکند.
البته باید حواسمان باشد که استفاده زیاد از این اپراتور میتواند خوانایی کد را پایین بیاورد؛ برای همین معمولاً بهتر است فقط در جاهایی استفاده شود که واقعاً کد را تمیزتر میکند.
حالا سراغ یک مورد عجیبتر برویم؛ چیزی که خیلی از برنامهنویسهای C حتی اسمش را هم کمتر شنیدهاند: Digraphs.
در زبان C، برای بعضی از نمادها، شکلهای جایگزین وجود دارد.
مثلاً به جای { و } میتوان از <% و %> استفاده کرد.
یعنی این کد:
int main() {
return 0;
}
میتواند به شکل زیر هم نوشته شود:
int main() <%
return 0;
%>
یا مثلاً به جای [ و ] میتوان از <: و :> استفاده کرد:
int arr<:3:> = <%1, 2, 3%>;که معادل این کد است:
int arr[3] = {1, 2, 3};
این قابلیت در گذشته برای سیستمهایی کاربرد داشت که بعضی کاراکترهای خاص مثل { یا [ روی کیبورد یا سیستمعاملشان بهراحتی در دسترس نبود.
امروزه Digraphها تقریباً کاربرد عملی خاصی ندارند و بیشتر بهعنوان یک ویژگی تاریخی و عجیب در زبان C شناخته میشوند. 😄
@Amin_TechLab1 962
❌ پیام آخرین Commit رو اشتباه نوشتید؟
لازم نیست برای اصلاحش یک Commit جدید بسازید.
اگر میخواهید پیام آخرین Commit را تغییر دهید، میتوانید از Interactive Rebase استفاده کنید:
git rebase -i HEAD~1
سپس در فایل بازشده، این خط را:
pick abc123 Fix logni pageبه این شکل تغییر دهید:
reword abc123 Fix logni pageبعد از ذخیره و خروج، Git از شما میخواهد پیام جدید Commit را وارد کنید:
Fix login page📌 دستورات مهم در Interactive Rebase:
pick → استفاده از Commit بدون تغییر
reword → تغییر پیام Commit
edit → ویرایش Commit
squash → ادغام با Commit قبلی
fixup → ادغام بدون نگه داشتن پیام Commit
drop → حذف Commit
💡 البته اگر فقط قصد دارید پیام آخرین Commit را تغییر دهید، معمولاً این دستور سریعتر و سادهتر است:
git commit --amend -m "NEW MESSAGE"
@Amin_TechLab1 962
❌ پیام آخرین Commit رو اشتباه نوشتید؟
لازم نیست برای اصلاحش یک Commit جدید بسازید.
اگر میخواهید پیام آخرین Commit را تغییر دهید، میتوانید از Interactive Rebase استفاده کنید:
git rebase -i HEAD~1
سپس در فایل بازشده، این خط را:
pick abc123 Fix logni page
به این شکل تغییر دهید:
reword abc123 Fix logni page
بعد از ذخیره و خروج، Git از شما میخواهد پیام جدید Commit را وارد کنید:
Fix login page
📌 دستورات مهم در Interactive Rebase:
pick → استفاده از Commit بدون تغییر
reword → تغییر پیام Commit
edit → ویرایش Commit
squash → ادغام با Commit قبلی
fixup → ادغام بدون نگه داشتن پیام Commit
drop → حذف Commit
💡 البته اگر فقط قصد دارید پیام آخرین Commit را تغییر دهید، معمولاً این دستور سریعتر و سادهتر است:
git commit --amend -m "NEW MESSAGE"
@Amin_TechLab
1 962
🐍 چرا Generic Typing در پایتون اهمیت دارد؟
بسیاری از توسعهدهندگان هنگام استفاده از Type Hinting فقط سراغ انواع مشخصی مثل
str، int یا list[str] میروند. اما وقتی یک تابع یا کلاس قرار است با چند نوع داده مختلف کار کند، Generic Typing به شما کمک میکند بدون از دست دادن Type Safety، کدی منعطفتر و قابلاستفادهتر بنویسید.
به جای اینکه برای هر نوع داده یک تابع جداگانه تعریف کنید، میتوانید یک Type Variable بسازید و نوع ورودی و خروجی را به آن وابسته کنید. در این حالت ابزارهایی مانند MyPy و Pyright نیز میتوانند ناسازگاریهای نوعی را قبل از اجرای برنامه تشخیص دهند.
from typing import TypeVar
T = TypeVar("T")
def first(items: list[T]) -> T:
return items[0]
در مثال بالا، تابع first میتواند لیستی از هر نوع دادهای را دریافت کند؛ اما نوع خروجی همیشه دقیقاً با نوع عناصر لیست یکسان خواهد بود.
برای درک بهتر قدرت Genericها، به مثال زیر توجه کنید:
def select[T](items: list[T]) -> T:
...
این تابع بسته به نوع دادهای که دریافت میکند، مقدار T را بهصورت خودکار تعیین میکند:
select([1, 2, 3, 4, 5]) # T = int select(["a", "b", "c"]) # T = str select([1.2, 1.3, 1.4]) # T = floatحتی برای انواع تعریفشده توسط خودتان نیز همین اتفاق میافتد:
users = [User("Abby"), User("Chris"), User("Nick")]
select(users) # T = User
همانطور که میبینید، نوع T ثابت نیست و بر اساس نوع دادهای که به تابع ارسال میشود تعیین خواهد شد. این دقیقاً جوهره Generic Typing است.
❓ چرا معمولاً از حرف T استفاده میشود؟
در واقع هیچ اجباری برای استفاده از T وجود ندارد. این فقط یک قرارداد رایج بین برنامهنویسان است؛ درست مثل بسیاری از Conventionهای دیگر در دنیای توسعه نرمافزار.
بنابراین کد زیر کاملاً معتبر است:
def duplicate[B](item: B) -> tuple[B, B, B]:
return (item, item, item)
همچنین میتوانید از چند Generic Type بهطور همزمان استفاده کنید:
def pair[A, B](first: A, second: B) -> tuple[A, B]:
return (first, second)
در این مثال، نوع A و B مستقل از یکدیگر هستند و میتوانند هر نوع دادهای را نمایش دهند.
Generic Typing یکی از ابزارهای مهم برای نوشتن کدهای reusable، type-safe و قابل نگهداری در پروژههای بزرگ پایتونی است.
📚 منبع:
https://blog.imsadra.dev/generic-typing-in-python
@Amin_TechLab1 962
🐍 آشنایی با چند اپراتور کمتر شناختهشده در پایتون
در پایتون، مقادیری که روی آنها عملیات انجام میشود را Operand و نماد انجامدهنده عملیات را Operator مینامیم.
برای مثال در کد زیر:
if x > y:
...
متغیرهای x و y نقش Operand را دارند و علامت > یک Operator است.
اما در میان اپراتورهای پایتون، موردی وجود دارد که خیلی از برنامهنویسها کمتر با آن آشنا هستند: Walrus Operator (:=).
این اپراتور علاوه بر انجام مقایسه یا ارزیابی یک عبارت، همزمان مقدار آن را در یک متغیر نیز ذخیره میکند.
مثلاً معمولاً کدی شبیه این مینویسیم:
length = len("test1234")
if length < 8:
print(f"Your password is {length} chars long.")
اما با استفاده از Walrus Operator میتوان همان کار را به شکل خلاصهتر انجام داد:
if (length := len("test1234")) < 8:
print(f"Your password is {length} chars long.")
نکته جالب اینجاست که فارغ از نتیجه شرط، متغیر length پس از اجرای این دستور همچنان در دسترس خواهد بود.
حالا سراغ یک اپراتور عجیبتر برویم؛ چیزی که احتمالاً هرگز در کدهای واقعی ندیدهاید!
در نسخههای قدیمی پایتون، برای عملگر «نامساوی» بهجای != از <> استفاده میشد. این سینتکس سالهاست منسوخ شده، اما هنوز بهعنوان یک ایستر اگ (Easter Egg) در پایتون وجود دارد.
from __future__ import barry_as_FLUFL
بعد از اجرای این دستور، پایتون شما را مجبور میکند به جای != از <> استفاده کنید:
>>> 2 != 3 SyntaxError: with Barry as BDFL, use '<>' instead of '!=' >>> 2 <> 3 Trueنام این قابلیت از Barry Warsaw، یکی از توسعهدهندگان قدیمی پایتون، گرفته شده است. البته کاربرد عملی خاصی ندارد و بیشتر یک شوخی تاریخی در دل زبان پایتون محسوب میشود. 😄 📚 منبع: https://blog.imsadra.dev/10-python-easter-eggs @Amin_TechLab
1 962
🔍 Unlimited-OCR by Baidu
A powerful OCR model from Baidu that takes things a step beyond DeepSeek-OCR. It features long-horizon parsing, enabling one-shot processing of lengthy documents—including single images, multi-page documents, and entire PDFs.
The model supports Transformers and SGLang, and delivers high-quality structured outputs for document understanding and information extraction.
🔗 github.com/baidu/Unlimited-OCR
@Amin_TechLab
1 962
❗️پیام موقت ❗️
درود دوستان
یکی از دوستان عزیز و همکاران بنده
که از لحاظ فنی و اخلاقی به صورت کامل مورد تایید بنده هستن .
جویای کار تخصصی در الکترونیک و امبدد سیستم هستن در شهر تهران .
به طور خلاصه بیش از ۳ سال تجربه کار طراحی دارند
مسلط به آلتیوم و طراحی مدار و ساخت برد .
تسلط کار با میکروکنترلر های avr,stm32,esp .
مسلط به زبان پایتون و سی .
لطفا دوستان هر شخص موقعیت شغلی داشتن لطفا به بنده پیام اعلام کنن تا رزومه و نمونه کار های ایشون رو ارسال کنم .
با تشکر از تمام عزیزان .
ای دی جهت ارسال پیام :
1 962
رفقا براتون یک سری رفرنس خوب برای آشنایی عمیق از لینوکس فرستادم .
اینکه چی میخونید برق یا کامپیوتر مهم نیست ، صفت بچسبید لینوکس یادبگیرید .
اگر لینوکس بلد بودید به نظرم میدونی کامپیوتر که حلوت هست چه جوری میتونی به بهترین و بهینه ترین شکل ممکن ازش استفاده کنید . اینو من راجب تمام سیستم عامل های unix بیس میکنم ولی اگر بلد نبودی به نظرم با اون حساب دار یا انبار داری که اکسل رو باز میکنه تو ویندوزش هیچ فرق نداریم .
اگر لینوکس بدونی ، یعنی سخت افزار رو درک کردی ،
اگر لینوکس بدونی یعنی میفهمی زبان برنامه سطح پایین چیه
اگر لینوکس بدونی یعنی سی بلدی
اگر لینوکس بدونی یعنی مدیریت تسک رو درک کردی
اگر لینوکس بدونی یعنی مهندسی رو فهمیدی ....
ارادمند تمام عزیزان 🫡🌹
@Amin_TechLab
1 962
Understanding the Linux Kernel
Daniel P. Bovet
Marco Cesati
Publisher: O'Reilly
@Amin_TechLab
👇👇👇👇👇👇👇
1 962
The Linux Programming inTerface
A Linux and UNIX®
System Programming Handbook
Michael KerrisK
@Amin_TechLab
1 962
The Linux Programming inTerface
A Linux and UNIX®
System Programming Handbook
Michael KerrisK
@Amin_TechLab
👇👇👇👇👇👇👇
Available now! Telegram Research 2025 — the year's key insights 
