Việc làm

2 ngày trước · Hồ Chí Minh · Hà Nội · Tại văn phòng

[EPM] SiL Embedded Engineer (C++) (Joining Bonus)

Bosch Global Software Technologies · Embedded Engineer

Xem mô tả & ứng tuyển trên ITviecMô tả công việc, lương và ứng tuyển nằm ở ITviec.

10 câu hỏi có thể gặp khi phỏng vấn

Chọn theo kỹ năng và cấp của tin (C/C++ & Embedded, Python, DevOps & CI/CD). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.

  1. 01Thiết bị nhúng thỉnh thoảng bị treo hoặc reset ngoài hiện trường. Bạn debug thế nào?C/C++ & Embedded · Senior

    Gợi ý trả lời

    Cần thu thập dấu vết từ thiết bị trước, sau đó tái hiện trong phòng lab.

    • Lưu nguyên nhân reset: đọc thanh ghi reset cause (watchdog, brown-out, hard fault) khi khởi động và ghi vào flash hoặc gửi log lên.
    • Hard fault handler: lưu các thanh ghi PC, LR và stack frame để biết lệnh gây lỗi, sau đó tra file .map hoặc addr2line.
    • Stack overflow: bật kiểm tra stack của RTOS, tô mẫu (stack painting) để đo mức dùng tối đa.
    • Watchdog: chỉ "đá" watchdog khi mọi task quan trọng còn sống, không đá trong ISR timer.
    • Kiểm tra phần cứng: nguồn sụt áp, nhiễu, nhiệt độ.

    Trong lab dùng JTAG/SWD với GDB, logic analyzer và chạy stress test dài.

    Người phỏng vấn muốn nghe: một ca thật bạn đã xử lý, cách khoanh vùng và cách chứng minh đã sửa đúng.

    Ôn thêm câu hỏi C/C++ & Embedded →
  2. 02Lập trình đa luồng trong C++ hiện đại: std::atomic, mutex và memory order dùng khi nào?C/C++ & Embedded · Senior

    Gợi ý trả lời

    Dữ liệu chia sẻ giữa các thread mà có ít nhất một thread ghi thì phải đồng bộ, nếu không là data race (undefined behavior).

    • std::mutex với std::lock_guard hoặc std::scoped_lock (khoá nhiều mutex không deadlock): dùng cho vùng găng có nhiều biến hoặc logic phức tạp.
    • std::atomic<T>: cho biến đơn lẻ như cờ, bộ đếm, không cần khoá.
    • Memory order: mặc định seq_cst an toàn nhất. acquire/release dùng cho mẫu producer/consumer; relaxed chỉ cho bộ đếm thống kê không cần thứ tự.
    • C++20 bổ sung std::jthread (tự join, có stop token), std::latch, std::barrier, std::counting_semaphore.
    std::atomic<int> hits{0};
    hits.fetch_add(1, std::memory_order_relaxed);
    

    Hay sai: dùng memory order yếu khi chưa thật hiểu, hoặc lock-free hoá sớm khi mutex đã đủ nhanh. Kiểm tra bằng ThreadSanitizer.

    Ôn thêm câu hỏi C/C++ & Embedded →
  3. 03Bạn thiết kế firmware thế nào để dễ test, dễ port sang vi điều khiển khác và áp dụng SOLID?C/C++ & Embedded · Senior

    Gợi ý trả lời

    Tách phần phụ thuộc phần cứng ra sau một lớp trừu tượng, để logic nghiệp vụ chạy và test được trên máy tính.

    • Phân lớp: driver thanh ghi / HAL → BSP → service (giao thức, lưu trữ) → application.
    • Dependency inversion: application phụ thuộc interface (struct chứa con trỏ hàm trong C, abstract class hoặc template trong C++), không gọi thẳng thanh ghi.
    • Single responsibility: mỗi module một việc, như đọc cảm biến, lọc tín hiệu, gửi dữ liệu.
    • Unit test trên host với Unity, CppUTest hoặc GoogleTest bằng driver giả; test trên phần cứng (HIL) cho phần còn lại.
    • Máy trạng thái (state machine) rõ ràng cho logic phức tạp.
    • CI build nhiều target, chạy static analysis và kiểm tra theo chuẩn code (vd. MISRA).

    Người phỏng vấn muốn nghe: bạn cân đối được giữa trừu tượng hoá và giới hạn RAM, flash, thời gian thực.

    Ôn thêm câu hỏi C/C++ & Embedded →
  4. 04Một API viết bằng Python (Django hoặc FastAPI) phản hồi chậm. Bạn tối ưu theo thứ tự nào?Python · Senior

    Gợi ý trả lời

    Đo trước, tối ưu chỗ tốn nhất trước. Phần lớn trường hợp nút thắt là DB và gọi mạng, không phải tốc độ của Python.

    1. Đo: APM hoặc tracing (OpenTelemetry) để biết thời gian nằm ở DB, API ngoài hay code. Profile bằng py-spy (gắn vào process đang chạy) hoặc cProfile.
    2. DB: xử lý N+1, thêm index phù hợp, chỉ lấy cột cần (only, values), phân trang.
    3. Cache: Redis cho dữ liệu đọc nhiều, ít đổi; nhớ chiến lược invalidate.
    4. Việc nặng hoặc không cần trả ngay (gửi email, xuất file): đẩy sang Celery hoặc queue.
    5. Gọi nhiều API ngoài: chạy song song, đặt timeout.
    6. Cuối cùng mới tới tối ưu thuật toán, hoặc đưa đoạn nặng CPU sang thư viện C hay service khác.

    Hay sai: viết lại sang async hoặc đổi ngôn ngữ trước khi biết thời gian thực sự bị tiêu ở đâu.

    Ôn thêm câu hỏi Python →
  5. 05Bạn tổ chức một codebase Python lớn nhiều người cùng làm như thế nào: type hints, quản lý dependency, chất lượng code?Python · Senior

    Gợi ý trả lời

    Python linh hoạt nên dự án lớn dễ rối; cần công cụ để bắt lỗi trước khi chạy.

    • Type hints + type checker (mypy hoặc pyright) chạy trong CI. Dùng Protocol cho interface, TypedDict hoặc dataclass thay cho dict tự do.
    • Validate dữ liệu ở biên (request, config, message) bằng Pydantic; bên trong tin vào kiểu đã kiểm.
    • Dependency: môi trường ảo riêng, file lock để build tái lập được (uv, Poetry hoặc pip-tools). Tách dependency dev và production.
    • Lint/format tự động: ruff thay cho nhiều công cụ cũ; chạy qua pre-commit và CI.
    • Cấu trúc: chia theo domain, tách logic nghiệp vụ khỏi framework để test không cần DB hay HTTP.
    • Test bằng pytest với fixture; test tích hợp cho các luồng chính.

    Người phỏng vấn muốn nghe: bạn hiểu type hints không kiểm tra lúc runtime, nên vẫn cần validate dữ liệu đầu vào.

    Ôn thêm câu hỏi Python →
  6. 06GitOps là gì? Bạn tổ chức repo và quy trình deploy cho nhiều môi trường, nhiều service ra sao?DevOps & CI/CD · Senior

    Gợi ý trả lời

    GitOps coi Git là nguồn sự thật cho trạng thái hệ thống; một agent trong cluster (Argo CD, Flux) liên tục kéo và đồng bộ, thay vì CI đẩy thẳng bằng kubectl.

    • Tách repo code ứng dụng và repo cấu hình deploy; CI build image rồi mở PR cập nhật tag.
    • Cấu hình dùng chung bằng Helm chart hoặc Kustomize, overlay riêng cho dev/staging/prod.
    • Lên prod qua PR có review; rollback bằng git revert.
    • Bật phát hiện drift và tự sửa lệch cấu hình.
    • CI không cần giữ credential admin của cluster.

    Người phỏng vấn muốn nghe: cân nhắc được đánh đổi, ví dụ secret vẫn cần giải pháp riêng và số lượng PR cập nhật tag có thể nhiều.

    Ôn thêm câu hỏi DevOps & CI/CD →
  7. 07Con trỏ và tham chiếu (reference) trong C++ khác nhau thế nào?C/C++ & Embedded · Junior

    Gợi ý trả lời

    Con trỏ là biến chứa địa chỉ, có thể nullptr và trỏ sang đối tượng khác. Tham chiếu là tên gọi khác của một đối tượng đã tồn tại, phải khởi tạo ngay và không gán lại được.

    int x = 1, y = 2;
    int* p = &x;  p = &y;   // đổi đối tượng được trỏ
    int& r = x;   r = y;    // gán giá trị y cho x
    
    • Truyền tham số: dùng const T& cho đối tượng lớn chỉ đọc, T& khi cần sửa, con trỏ khi tham số có thể vắng mặt.
    • Có con trỏ tới con trỏ và phép toán số học trên con trỏ; tham chiếu thì không.

    Hay sai: trả về tham chiếu hoặc con trỏ tới biến cục bộ. Biến bị huỷ khi hàm kết thúc và dùng nó là undefined behavior.

    Ôn thêm câu hỏi C/C++ & Embedded →
  8. 08Stack và heap khác nhau thế nào? Memory leak và dangling pointer là gì?C/C++ & Embedded · Junior

    Gợi ý trả lời

    Stack chứa biến cục bộ, cấp phát và giải phóng tự động theo phạm vi hàm, rất nhanh nhưng kích thước nhỏ. Heap cấp phát động (new/malloc), sống đến khi giải phóng thủ công, linh hoạt nhưng chậm hơn và dễ phân mảnh.

    • Memory leak: cấp phát trên heap mà không giải phóng, bộ nhớ tăng dần. Trên thiết bị nhúng chạy lâu ngày đây là lỗi chết người.
    • Dangling pointer: con trỏ vẫn giữ địa chỉ của vùng nhớ đã giải phóng hoặc biến đã hết phạm vi.
    • Double free: giải phóng một vùng hai lần.

    Phòng tránh: dùng RAII và smart pointer trong C++, đặt con trỏ về NULL sau free trong C, kiểm tra bằng AddressSanitizer hoặc Valgrind.

    Người phỏng vấn muốn nghe (nhúng): nhiều hệ thống hạn chế hoặc cấm cấp phát động sau khi khởi động, dùng memory pool hoặc mảng tĩnh.

    Ôn thêm câu hỏi C/C++ & Embedded →
  9. 09Từ khoá volatile dùng để làm gì trong lập trình nhúng?C/C++ & Embedded · Junior

    Gợi ý trả lời

    volatile báo cho compiler rằng giá trị biến có thể thay đổi ngoài luồng code hiện tại, nên mỗi lần truy cập phải đọc hoặc ghi thật vào bộ nhớ, không được tối ưu bỏ hay cache vào thanh ghi.

    Dùng cho:

    • Thanh ghi phần cứng ánh xạ bộ nhớ (memory-mapped register).
    • Biến chia sẻ giữa ISR (hàm phục vụ ngắt) và vòng lặp chính.
    volatile bool data_ready = false;
    void UART_IRQHandler(void) { data_ready = true; }
    while (!data_ready) { }  // không có volatile có thể thành lặp vô hạn
    

    Hay sai: nghĩ volatile đảm bảo thread-safe hoặc atomic. Nó không chống race condition và không tạo memory barrier giữa các core; cần atomic, tắt ngắt hoặc mutex.

    Ôn thêm câu hỏi C/C++ & Embedded →
  10. 10Điểm mạnh lớn nhất của bạn là gì?Câu hỏi hành vi & văn hoá

    Gợi ý trả lời

    Chọn một hai điểm mạnh liên quan tới vị trí, và chứng minh bằng ví dụ thật, không liệt kê tính từ.

    Cấu trúc: điểm mạnh, ví dụ ngắn, kết quả, liên hệ với công việc mới.

    Câu mẫu: "Điểm mạnh của em là chủ động tìm nguyên nhân gốc. Ở dự án trước, hệ thống thỉnh thoảng bị timeout mà không ai tái hiện được. Em tự đọc log, thêm theo dõi ở các điểm nghi ngờ và tìm ra một truy vấn bị khoá bảng vào giờ cao điểm. Sau khi sửa, lỗi đó không còn xuất hiện. Em nghĩ điều này hữu ích với vị trí bên mình vì hệ thống có lượng truy cập lớn."

    Hay sai: "Em chăm chỉ, ham học hỏi, chịu được áp lực" mà không có ví dụ. Ai cũng nói vậy nên không đọng lại gì.

    Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →

Bạn đã phỏng vấn ở Bosch Global Software Technologies?

Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.

Chia sẻ kinh nghiệm phỏng vấn