الرئيسية قاعدة المعرفة البرمجة والمنطق لغة Rust في الأنظمة الصناعية
البرمجة والمنطق

لغة Rust في الأنظمة الصناعية

لماذا Rust للصناعة؟

تخيّل أنك تشغّل خط إنتاج يحوي 200 مستشعر حرارة وضغط واهتزاز، وبرنامج التحكم يتوقف فجأة بسبب null pointer — الآلات تستمر بالدوران بلا مراقبة. هذا السيناريو يحدث يومياً في أنظمة مكتوبة بـ C و C++. لغة Rust وُلدت لحل هذه المشكلة تحديداً.

Rust تُقدّم أمان الذاكرة بدون جامع قمامة (Garbage Collector). المُجمِّع (Compiler) يكتشف أخطاء الذاكرة — تسريبات، مؤشرات معلّقة، سباقات بيانات — قبل أن يعمل البرنامج أصلاً. في البيئة الصناعية، هذا يعني: صفر أعطال مفاجئة في وقت التشغيل.

لهذا اختار فريق Dr. Machine لغة Rust لبناء منصة ERP صناعية كاملة — من خادم الويب إلى قراءة المستشعرات.

الملكية والاستعارة: أمان بلا كلفة

نظام الملكية (Ownership) هو قلب Rust. القاعدة بسيطة: لكل قيمة في الذاكرة مالك واحد فقط. عندما يخرج المالك من النطاق، تُحرَّر الذاكرة تلقائياً.

fn process_reading() {
    let data = vec![23.5, 24.1, 22.8]; // data تملك هذا Vec
    analyze(data);  // الملكية انتقلت إلى analyze
    // لا يمكن استخدام data هنا — المُجمِّع يمنعك
}

الاستعارة (Borrowing) تسمح بالوصول المؤقت دون نقل الملكية:

fn log_temperatures(readings: &[f64]) {
    // نقرأ فقط — لا نملك البيانات
    for temp in readings {
        println!("درجة الحرارة: {:.1}°C", temp);
    }
}

هذا النظام يمنع سباقات البيانات (Data Races) في وقت التجميع — وهو أمر حاسم عندما تقرأ عدة مهام من نفس المستشعر في وقت واحد.

التعامل مع الأخطاء: لا أعطال مفاجئة

في C++ قد تحصل على nullptr وينهار البرنامج. في Rust لا وجود لـ null. بدلاً منه تستخدم نوعين:

  • Option<T>: إما Some(value) أو None — للقيم التي قد لا تكون موجودة
  • Result<T, E>: إما Ok(value) أو Err(error) — للعمليات التي قد تفشل
fn read_sensor(id: u8) -> Result<f64, SensorError> {
    let raw = hardware_read(id)?; // ? تنقل الخطأ تلقائياً
    if raw == 0xFFFF {
        return Err(SensorError::Disconnected);
    }
    Ok(raw as f64 / 10.0)
}

المُجمِّع يُجبرك على معالجة كل حالة خطأ — لا يمكنك تجاهلها. هذا يعني أن برنامجك الصناعي لن ينهار بسبب خطأ لم تتوقعه.

البرمجة غير المتزامنة: آلاف المستشعرات

مصنع حديث قد يحوي آلاف المستشعرات. قراءتها واحداً تلو الآخر بطيئة جداً. البرمجة غير المتزامنة (Async) تسمح بقراءة مئات المستشعرات "في نفس الوقت" على خيط واحد.

Rust تستخدم async/await مع مكتبة tokio — نفس التقنية التي تشغّل خوادم تخدم ملايين الطلبات:

use tokio::time::{interval, Duration};

async fn monitor_all_sensors(sensors: Vec<u8>) {
    let mut tick = interval(Duration::from_secs(1));
    loop {
        tick.tick().await;
        let tasks: Vec<_> = sensors.iter()
            .map(|&id| tokio::spawn(read_sensor(id)))
            .collect();

        for task in tasks {
            match task.await.unwrap() {
                Ok(temp) => log_value(temp),
                Err(e) => alert_operator(e),
            }
        }
    }
}

هذا الكود يقرأ جميع المستشعرات بالتوازي كل ثانية — بدون إنشاء خيوط نظام ثقيلة.

مثال: قراءة مستشعر حرارة عبر Modbus

Modbus RTU هو البروتوكول الأكثر انتشاراً في المصانع. إليك مثال واقعي لقراءة مستشعر حرارة PT100 من جهاز على العنوان 3، السجل 40001:

use tokio_modbus::prelude::*;
use tokio_serial::SerialPortBuilderExt;

async fn read_temperature() -> Result<f64, Box<dyn std::error::Error>> {
    let serial = tokio_serial::new("/dev/ttyUSB0", 9600)
        .open_native_async()?;

    let mut ctx = rtu::attach_slave(serial, Slave(3));
    let response = ctx.read_holding_registers(0x0000, 1).await?;

    let raw_value = response[0];
    let temperature = raw_value as f64 / 10.0;

    println!("درجة الحرارة: {:.1}°C", temperature);
    Ok(temperature)
}

البرنامج يفتح منفذ تسلسلي، يتواصل مع الجهاز رقم 3 عبر بروتوكول Modbus RTU، يقرأ السجل، ويحوّل القيمة الخام إلى درجة مئوية. لاحظ كيف أن ? تعالج كل الأخطاء المحتملة — فتح المنفذ، الاتصال، القراءة — بسطر واحد.

Rust مقابل C++ في البيئات الصناعية

المعيار Rust C++
أمان الذاكرة مضمون وقت التجميع مسؤولية المبرمج
المؤشرات المعلّقة مستحيلة سبب شائع للأعطال
سباقات البيانات يمنعها المُجمِّع تكتشف وقت التشغيل (إن حالفك الحظ)
الأداء مكافئ لـ C++ مرجع الأداء
وقت التجميع أبطأ أسرع
المكتبات الصناعية متنامية (tokio-modbus, embedded-hal) ناضجة وواسعة
منحنى التعلم حاد في البداية متوسط لكن الأخطاء تظهر لاحقاً

الأداء متكافئ عملياً — الفرق الجوهري هو أن Rust تمنع فئات كاملة من الأخطاء التي تسبب توقف الإنتاج في أنظمة C++.

Rust تدعم أيضاً الأنظمة المدمجة (Embedded) عبر no_std — يمكنك كتابة برنامج يعمل على متحكم ARM بدون نظام تشغيل، مع نفس ضمانات الأمان.

الخلاصة

Rust تجمع بين أداء C++ وأمان لا تقدمه أي لغة أنظمة أخرى. نظام الملكية يمنع تسريبات الذاكرة والمؤشرات المعلّقة وقت التجميع. أنواع Result و Option تقضي على الأعطال المفاجئة. البرمجة غير المتزامنة مع tokio تتيح مراقبة آلاف المستشعرات بكفاءة. في بيئة صناعية حيث التوقف يعني خسائر بالآلاف في الدقيقة — هذه الضمانات ليست ترفاً، بل ضرورة.

Rust ownership borrowing async Modbus memory-safety لغة رست الملكية والاستعارة البرمجة غير المتزامنة أمان الذاكرة الأنظمة المدمجة Tokio