Lựa Chọn Bản Phân Phối

Nếu bạn có ý định sắm cho mình một chiếc điện thoại mới, bạn cần xem xét yếu tố nào?

Khả năng tài chính, kích thước, màu sắc, thương hiệu, camera, ram,… hay đơn giản chỉ vì bạn thích.

Cũng giống như việc bạn chọn mua một chiêc điện thoại, lựa chọn một bản phân phối Linux cũng cần cân nhắc một số yếu tố như:

  • Chức năng chính của hệ thống là gì (máy chủ, máy tính để bàn hay hệ thống nhúng,…)?
  • Công việc nào là quan trọng với tổ chức? (lướt web, xử lý công việc văn phòng,…)
  • Có bao nhiêu không gian trống trên ổ đĩa?
  • Hệ thống của bạn có cần cập nhật thường xuyên không?
  • Thời gian hỗ trợ cho hệ thống là bao lâu?
  • Có cần tùy chỉnh kernel không?
  • Phần cứng mà hệ điều hành sẽ chạy? (x86, ARM, PPC,…)
  • Hệ thống có cần sự ổn định hay chỉ thử nghiệm ngắn hạn?

Sau khi đã có đáp án cho các câu hỏi trên, bạn sẽ đưa ra quyết định lựa chọn bản phân phối cho hệ thống của mình.

Quy trình cài đặt là tương tự cho các bản phân phối. Ở đây, tôi sẽ hướng dẫn trên Ubuntu, các bản phân phối khác cũng tương tự. Lý do tôi chọn Ubuntu là vì nó được sử dụng khá phổ biến, khá dễ sử dụng (sử dụng gần giống Windows). Tôi sử dụng máy ảo VMWare và cài đặt Ubuntu trên đó để học. Nếu bạn không có điều kiện mua máy tính để học Linux thì đây là một trong những cách hay mà bạn có thể lựa chọn. Trên máy ảo này, ngoài việc cài đặt Ubuntu, bạn còn có thể cài đặt CentOS, openSUSE, chúng là những bản phân phối Linux được sử dụng phổ biến nhất.

Để cài đặt máy ảo VMWare, bạn có thể làm theo hướng dẫn ở đây.

Việc cài đặt Ubuntu lên máy áo cũng khá đơn giản, bạn có thể làm theo hướng dẫn này.

Trong các bài hướng dẫn tiếp theo, bạn sẽ được làm quen với việc sử dụng Linux.

Advertisements

Hệ Thống Tập Tin Và Package Trong Linux

Quản lý tập tin

Linux có cách tổ chức, sắp xếp và lưu trữ tập tin giống như một chiếc tủ vậy. Nghĩa là, nó cũng có nhiều ngăn, mỗi ngăn chứa đồ vật cùng loại, hình dạng hay kích cỡ.

Các kiểu tập tin hệ thống mà Linux hổ trợ gồm có:

  • Các tập tin ở ổ đĩa thông thường: ext2, ext3, ext4, XFS, Btrfs, JFS, NTFS,…
  • Tập tin hệ thống lưu trữ Flash: ubifs, JFFS2, YAFFS,…
  • Tập tin cơ sở dữ liệu
  • Các tập tin hệ thống đặc biệt: procfs, sysfs, tmpfs, debugfs,…

partitions (phân vùng) là 1 phần của ổ đĩa, trong khi filesystem là phương pháp tìm kiếm/lưu trữ files trên đĩa cứng. Tương tự, bạn có thể tưởng tượng filesystem giống như một cuốn sổ gia phả cho thấy các thành viên trong dòng họ và mối quan hệ của họ, trong khi partitions là mỗi gia đình khác nhau.

Capture

Phía trên là sự so sánh sự khác biệt trong filesystem của Windows và Linux.

Linux lưu trữ những file quan trọng theo tiêu chuẩn cấp bậc gọi là Filesystem Hierarchy Standard (FHS). Đó là một tiêu chuẩn giúp cho người dùng, quản trị viên và nhà phát triển có thể chuyển sang các bản phân phối khác mà không cần tìm hiểu lại hệ thống được tổ chức như thế nào. Khác với Windows, Linux sử dụng ký tự ‘/’ để tách các đường dẫn thay vì ‘\’ và nó cũng không có ký tự ổ đĩa như trên Windows.

Một điều cần lưu ý là các filesystem trên Linux phân biệt giữa chữ thường và chữ hoa.

Quản lý Package

Các bản phân phối Linux cũng giống như trò chơi lego vậy, nghĩa là nó cũng bao gồm nhiều mảnh được ghép lại với nhau tạo thành một hệ thống, mỗi mãnh ghép đó trong Linux được gọi là package. Các package điển hình như kernel, trình biên dịch C/C++, các mã phần mềm để tương tác với thiết bị USB, trình duyệt web.

Các package thường có mối quan hệ và phụ thuộc với nhau. Ví dụ như Firefox giao tiếp bằng SSL/TLS, nên nó phụ thuộc vào package có khả năng mã hóa và giải mã SSL và TLS, nó sẽ không cài đặt được trừ khi package mà nó phụ thuộc được cài đặt đồng thời.

Chúng ta cùng điểm qua Package Management trong gia đình Debian. dpkg là trình quản lý package cơ bản trong hệ thống này. Nó có thể cài đặt, gỡ bỏ và cập nhật phần mềm. Không giống như các hệ thống quản lý package cấp cao, nó không tự động download và cài đặt các package.

Trong khi đó apt (Advanced Package Tool) là trình quản lý package cấp cao hơn. apt tạo ra giao diện người dùng riêng cho nó (ví dụ apt-get, aptitude, synaptic, Ubuntu Software Center, Update Manager,…).

Giờ đây, trên Ubuntu, bạn có thể dễ dàng cài đặt, xóa các phần mềm nhờ việc tích hợp các trình quản lý package cấp cao apt.

Khởi Động Hệ Thống

Có bao giờ bạn tự hỏi, chuyện gì xảy ra kể từ khi bạn nhấn nút nguồn cho đến khi màn hình đăng nhập xuất hiện?

Đó là quá trình khởi động, là một thủ tục để khởi tạo hệ thống. Nó bao gồm mọi thứ xảy ra khi bạn nhấn nút nguồn đến khi giao diện người dùng hiển thị.

Khi bạn hiểu rõ các bước về quá trình khởi động, có thể giúp bạn khắc phục các sự cố, cũng như điều chỉnh hiệu năng của máy tính theo nhu cầu của bạn. Đây là một kỹ thuật nâng cao. Bạn có thể quay trở lại nghiên cứu điều này sau.

>> Power On

>> BIOS

>> Master Boot Record (MBR)

>> Boot Loader

>> Kernel (Linux OS)

>> Khởi tạo RAM

>> /sbin/init

>> Command Shell using getty

>> X Windows System (Graphical User Interface)

1. BIOS, bước đầu tiên. Khi hệ thống được bật, Basic Input/Output System (BIOS) bắt đầu quá trình khởi tạo phần cứng, bao gồm màn hình và bàn phím, kiểm tra bộ nhớ chính. Quá trình này còn được gọi là POST (Power On Self Test). Phần mềm BIOS được lưu trữ trong một chip ROM trên board mạch chủ. Sau đó, phần còn lại của quá trình khởi động được điều khiển bởi hệ điều hành (OS).

2. Khi POST hoàn tất, hệ thống sẽ chuyển sang giai đoạn của bộ nap khởi động (MBR). Trình nạp khởi động được lưu trữ trên các đĩa cứng trong hệ thống hoặc trong khu vực khởi động (dành cho các hệ thống BIOS/MBR truyền thống) hoặc phân vùng EFI (đối với các hệ thống hiện đại (Unified) Extensible Firmware Interface hoặc EFI/UEFI). Trong giai đoạn này, hệ thống không truy cập bất kỳ phương tiện lưu trữ truyền thông nào. Sau đó, thông tin về ngày tháng, thời gian, các thiết bị ngoại vi quan trọng nhất được nạp vào từ giá trị của CMOS (công nghệ này được áp dụng sau khi công nghệ theo dõi pin ra đời – cho phép hệ thống theo dõi ngày giờ ngay cả khi nó bị tắt). Một số bộ tải khởi động phổ biến như GRUB (GRand Unified Boot loader), ISOLINUX (dành cho việc khởi động từ các phương tiện di động) và DAS U-Boot (dành cho các ứng dụng hoặc thiết bị nhúng). Các trình nạp khởi động Linux có thể liệt kê một danh sách các lựa chọn thay thế cho việc nạp khởi động Linux. Khi khởi động Linux, trình nạp khởi động có nhiệm vụ tải file image kernel và RAM hoặc hệ thống tập tin ban đầu (chứa các tệp quan trọng và trình điều khiển thiết bị cần thiết để khởi động hệ thống) vào bộ nhớ.

3. Trình nạp khởi động có 2 giai đoạn riêng biệt:

Giai đoạn đầu:

Đối với các hệ thống truyền thống sử dụng phương pháp BIOS/MBR, trình khởi động nằm ở khu vực đầu tiên của đĩa cứng, còn được gọi là Master Boot Record (MBR). Kích thước của MBR chỉ là 512 byte. Trong giai đoạn này, bộ tải khởi động sẽ kiểm tra phân vùng và tìm thấy một phân vùng có khả năng khởi động. Một khi nó tìm thấy một phân vùng khởi động, nó sẽ tìm kiếm bộ nạp khởi động thứ hai, ví dụ như GRUB và nạp nó vào RAM (Random Access Memory).

Đối với các hệ thống hiện đại sử dụng phương pháp EFI/UEFI, UEFI Firmware đọc dữ liệu trình quản lý khởi động của nó để biết UEFI nào sẽ được khởi chạy và chạy từ đâu (ví dụ từ đĩa và phân vùng có thế tìm thấy trên EFI). UEFI Firmware sau đó sẽ chạy ứng dụng EFI, ví dụ GRUB, như định nghĩa trong mục nhập khởi động trong trình quản lý khởi động của phần mềm. Thủ tục này phức tạp hơn, nhưng linh hoạt hơn các phương pháp MBR cũ.

Giai đoạn hai:

Bộ nạp khởi động thứ 2 nằm dưới /boot. Lúc này, màn hình sẽ hiển thị cho phép lựa chọn hệ điều hành (OS) để khởi động. Sau khi lựa chọn hệ điều hành, trình tải khởi động sẽ tải kernel của hệ điều hành đã chọn vào RAM và chuyển quyền điều khiển cho nó. Kernel hầu như luôn luôn ở trạng thái bị nén, nên công việc đầu tiên của nó là giải nén bản thân mình. Sau đó, nó kiểm tra và phân tích phần cứng hệ thống, khởi tạo bất kỳ trình điều khiển nào được tích hợp trong kernel.

4. Khởi tạo RAM, các tập tin hệ thống initramfs chứa các chương trình và các tập tin nhị phân thực hiện tất cả các hành động cần thiết để gắn kết đúng hệ thống tập tin gốc, cũng như cung cấp các chức năng cần thiết và các trình điều khiển thiết bị cho bộ điều khiển lưu trữ với một cơ sở được gọi là udev (User Device), để tìm ra thiết bị nào có mặt, tìm các trình điều khiển để hoạt động đúng, và nạp chúng vào. Sau khi hệ thống tập tin gốc được tìm thấy, nó được kiểm tra lỗi và được gắn kết lại.

5. Lúc này, hệ điều hành đã biết rằng các file hệ thống đã sẵn sàng để sử dụng và kết hợp nó với những điểm cụ thể trong hệ thống phân cấp tổng thể của hệ thống tập tin. Nếu điều này thành công, initramfs sẽ được xóa khỏi RAM và chương trình init trên hệ thống tập tập tin gốc (/sbin/init) sẽ được thực hiện. init xử lý các gắn kết và pivoting trên hệ thống tập tin gốc cuối cùng. Nếu cần có trình điều khiển phần cứng đặc biệt trước khi lưu trữ có thể được truy cập, chúng sẽ trong file initramfs image.

6. Ở phần cuối của quá trình khởi động, init khởi động một số nhắc nhở đăng nhập ở chế độ văn bản. Các tính năng này cho phép bạn nhập vào tên người dùng, mật khẩu. Tuy nhiên, nếu bạn chạy một hệ thống có giao diện đồ họa thì bạn sẽ không thấy chúng.

Một khi kernel đã thiết lập tất cả phần cứng của nó và gắn kết các hệ thống tập tin gốc, kernel chạy chương trình /sbin/init. Điều này được thưc hiện sau tiến trình khởi động, sau đó, nó bắt các tiến trình khác của hệ thống khởi chạy. Hầu hết các tiến trình khác trên hệ thống đều được trace từ chúng đến init, ngoại lệ là các tiến trình kernel, bắt đầu trực tiếp bởi kernel để quản lý chi tiết nội bộ hệ điều hành.

Bên cạnh việc khởi chạy hệ thống, init còn có nhiệm vụ giữ cho hệ thống chạy và tắt nó sạch sẽ. Một trong những trách nhiệm của nó là hành động khi cần thiết như người quản lý tất cả các tiến trình không phải kernel, nó dọn dẹn sau khi chạy xong, và khởi động lại dịch vụ đăng nhập khi người dùng cần thiết đăng nhập vào/ra, và cũng làm như vậy cho các hệ thống khác.

Theo truyền thống, quá trình khởi động này thực hiện các quy ước System V UNIX, với hệ thống đi qua một chuỗi runlevel chứa các bộ sưu tập kịch bản bắt đầu và kết thúc các service. Mỗi runlevel hỗ trợ một chế độ chạy hệ thống khác nhau. Trong mỗi cấp độ, các dịch vụ cá nhân có thể được thiết lập để chạy hoặc tắt. Tuy nhiên, các bản phân phối gần đây, đã chuyển sang sử dụng các phương pháp khởi động mới.

Quá trình khởi động của các hệ thống cũ (SysVinit) được xem như một quá trình nối tiếp, được chia thành các giai đoạn tuần tự. Giai đoạn sau chỉ thực hiện khi giai đoạn trước hoàn thành. Vì thế, quá trình khởi động này không tận dụng được sức mạnh của việc xử lý song song trên các bộ vi xử lý.

Trước đây, việc tắt/mở hệ thống được xem là một hành động hiếm gặp và người ta cũng không quan trọng thời gian tắt/mở. Nhưng ngày nay, điều này đã không còn đúng nữa, đặc biệt là với các thiết bị di động và các hệ thống nhúng Linux. Các hệ thống hiện đại yêu cầu những giải pháp mang lại hiệu quả cao hơn. Các phương pháp cũ đòi hỏi kịch bản khá phức tạp, gây khó khăn cho việc phổ quát trên các bản phân phối, các phiên bản kernel, kiến trúc và các hệ thống.

Người ta đã đề ra 2 giải pháp, đó là:

1. Upstart

  • Được phát triển bởi Ubuntu và được đưa vào sử dụng lần đầu tiên vào 2006
  • Được thông qua trong Fedora 9 (2008), trong RHEL 6 và các bản sao của nó.

2. systemd

  • Được Fedora thông qua lần đầu vào 2011
  • Được thông qua bởi RHEL 7 và SUSE
  • Thay thế Upstart trên Ubuntu 16.04

Việc chuyển đổi các phương pháp khởi động đã gây ra khá nhiều tranh cãi trong cộng đồng. Nhưng việc áp dụng phổ quát các phương pháp mới này đã làm cho Linux đơn giản hơn, hiệu quả hơn vì có ít sự khác biệt giữa các bản phân phối.

Sức mạnh của systemd: Hệ thống khởi động với systemd đã cho thấy hiệu quả hơn hẳn so với phương pháp init trước đó. Điều này có được là nhờ việc thay thế các bước tuần tự thành song song, cho phép nhiều dịch vụ khởi tạo đồng thời. Các kịch bản khởi động phức tạp được thay thế bằng các tập tin cấu hình đơn giản. Nó liệt kê các công việc cần làm trước khi service được khởi chạy, làm thế nào để khởi chạy service và điều kiện nào service nên được chỉ ra khi hoàn tất quá trình khởi động.

Một lệnh systemd (systemctl) được sử dụng cho hầu hết các tác vụ cơ bản.

Bắt đầu, dừng hay khởi động lại 1 service:
sudo systemctl start/stop/restart fooservice

Kích hoạt hoặc ngưng kích hoạt service:
sudo systemctl enable/disable fooservice

Ngoài ra, còn có rất nhiều khác biệt giữa phương pháp khởi động mới và cũ nữa.

Giới Thiệu Về Hệ Điều Hành Linux

Ngày nay, có rất nhiều công việc sử dụng Linux nhưng lại không có đủ quản trị viên và nhà phát triển để đáp ứng nhu cầu đó. Các nền tảng Linux tồn tại thì ngày càng nâng cao và càng được sử dụng hiệu quả hơn để đáp ứng các nhu cầu thị trường. Và nó cũng cần một đội ngũ giỏi đề phát triển và đóng góp để nó có thể tiến xa hơn nữa.

Linus Torvalds, cha đẻ của Linux đã từng nói “Linux rất đơn giản, nhưng bạn cần phải có một bộ óc thiên tài để hiểu sự đơn giản đó”. Quả thực, hệ điều hành Linux không dễ nhưng cũng không khó để có thể sử dụng. Làm thế nào để có thể hiểu biết về Linux? Làm thế nào để có thể tiếp cận, sử dụng và đóng góp cho Linux? Đó là những câu hỏi mà bất kỳ ai cũng đặt ra khi bước chân vào ngôi đền mang tên Linux.

Các tài liệu về Linux nằm rải rác khắp mọi nơi và người dùng rất khó tiếp cận, cũng như rất khó biết được mình nên bắt đầu từ đâu. Trong quá trình học tập, mình đã cô đọng lại những kiến thức này, nhằm mang đến sự tiếp cận nhanh chóng và bền vững cho các bạn.

Trước tiên, chúng ta cần nhìn lại một chút về lịch sử và những điều có thể bạn chưa biết về Linux. Let’s go!

Hệ điều hành Linux được biết đến như một project mã nguồn mở lớn nhất của nhân loại, với biểu tượng là chú chim cánh cụt.

Năm 1991, Linus Torvalds – một sinh viên của Helsinki, Phần Lan đã bắt đầu một dự án viết kernel (hạt nhân) cho hệ điều hành riêng của mình. Ông đã tập hợp các thành phần thiết yếu khác nhau để xây dựng nên một hệ điều hành với kernel của ông. Năm 1992, Linux được cấp phép sử dụng General Public License (GPL) bởi GNU khiến cho cộng đồng thế giới chấp nhận và phát triển nó. Bằng cách kết hợp kernel và các thành phần hệ thống khác từ GNU, rất nhiều nhà phát triển đã cho ra đời các bản phân phối Linux.

Bằng việc sử dụng Linux làm nền tảng, các công ty như IBM, Oracle đã phát triển các phiên bản của riêng họ vào những năm 90 của thế kỉ XX. Có thể bạn chưa biết, ngày nay, Linux đang ngày càng phổ biến, nó chiếm đến hơn 1 nửa số máy chủ trên toàn thế giới, điện thoại thông minh (Android được xây dựng trên Linux) và các siêu máy tính.

Linux được phát triển không ngừng, liên tục cải tiến với người đứng đầu là Linux Torvalds. Nó mượn rất nhiều từ hệ điều hành UNIX vì nó là một phiên bản miễn phí và mã nguồn mở của UNIX. Ngoài ra, Linux còn được biết đến là một hệ điều hành đa người dùng. Có rất nhiều cộng đồng, diễn đàn thảo luận về Linux, bạn có thể tìm kiếm trên google. Hàng năm, Linux cũng tổ chức các buổi gặp gỡ, thảo luận với các nhà phát triển khắp nơi trên thế giới.

Trước khi tìm hiểu về Linux, bạn cần biết một số khái niệm về nó, chẳng hạn như, Kernel, bản phân phối, các thành phần và cấu hình của nó.

Kernel là cốt lõi của một hệ điều hành. Bạn có thể dễ dàng tìm thấy các phiên bản kernel tại kernel.org.

Một bản phân phối đầy đủ bao gồm hạt nhân cộng với một số công cụ khác cho hoạt động liên quan đến tập tin, quản lý người dùng và phần mềm. Mỗi công cụ cung cấp một phần nhỏ của hệ thống hoàn chỉnh, nó là một dự án của riêng của nhà phát triển, được đóng góp vào để hoàn thiện hệ thống. Các công cụ thiết yếu bao gồm trình biên dịch C/C++, trình gỡ rối gdb, các ứng dụng thư viện hệ thống cốt lõi, giao diện đồ họa, hệ thống cài đặt và cập nhật phần mềm, bao gồm cả bản thân kernel.

Các bản phân phối của Linux cũng rất đa dạng, chúng được thiết kế với mục đích phục vụ cho nhiều đối tượng và tổ chức khác nhau, tùy theo yêu cầu và sở thích của người dùng. Các tổ chức và các công ty lớn có khuynh hướng chọn các bản phân phối thương mại như Red Hat, SUSE, Ubuntu.

CentOS là một lựa chọn phổ biến cho Red Hat Enterprise (RHEL), nó được sự dụng thoải mái mà không cần phải trả phí. Trong khi đó Ubuntu và Fedora lại phổ biến trong lĩnh vực giáo dục. Các bản phân phối thương mại như Red Hat, Ubuntu, SUSE, Oracle cung cấp dịch vụ hỗ trợ dài hạn, các bản phân phối này sẽ được cập nhật để giữ cho hệ thống tăng cường tính bảo mật, cải tiến hiệu năng cũng như cung cấp tài nguyên hỗ trợ trực tuyến.

Trong bài tiếp theo, chúng ta sẽ cùng tìm hiểu về boot process, cài đặt linux,…

Xây Dựng Buffer Của Riêng Bạn

Trong lập trình hệ thống nhúng, bạn thường phải giao tiếp MCU với các thiết bị bên ngoài thông qua serial interface như UART, SPI, I2C,… Các ngoại vi này, thông thường chỉ hổ trợ truyền/nhận 1 byte data thôi. Khi bạn cần truyền nhận số lượng lớn data, bạn cần xây dựng nơi chứa các data, nơi chứa này được gọi là “buffer”.

Buffer (bộ đệm), về bản chất là mảng chứa data mà ta muốn gửi đi hoặc nhận về. Để dễ hình dung, bạn có thể tưởng tượng buffer là một cái ống (rỗng 2 đầu và có tiết diện vừa 1 cái bánh) và data là cái bánh. Khi bạn nhận bánh (data) với số lượng lớn, trong khoảng thời gian đó, bạn ăn không thể nào ăn hết, bạn cần cất giữ (put) chúng để có thể ăn sau, bạn cất giữ chúng trong 1 ống (buffer), khi nào đói, bạn đem ra ăn (get), nhưng bánh nào vào trước thì phải ra trước để bảm bảo hạn sử dụng.

Ngoài việc chứa data đơn thuần, buffer còn cho ta biết:

  • Kích cỡ của buffer, kích cỡ này là độ lớn của mảng thôi, trong C thì độ lớn của mảng phải là 1 hằng số.
  • Lượng data đang có trong buffer, để quản lý và biết được lượng data đang có trong buffer, ta cần đến 2 biến: 1 biến quản lý ở đầu và 1 biến quản lý đuôi.
  • Con trỏ chỉ đến mảng chứa data.

Từ những thuộc tính cơ bản trên, ta có thể xây dựng được bộ buffer đơn giản rồi.

typedef struct{
uint32_t head;
uint32_t tail;
uint32_t size;
uint8_t *arr;
}Buffer_Struct;

Như vậy là ta đã khai báo xong một kiểu dữ liệu mới có tên Buffer_Struct rồi, phần khai báo này nên đặt trong file .h nhé.

Một buffer có những hành động nào?

  1. Khởi tạo, đây là hành động được đặt lên đầu tiên vì độ quan trọng của nó.
  2. Đặt 1 data vào, bạn sẽ đặt data vào đây để lưu trữ nó.
  3. Lấy 1 data ra, bạn sẽ lấy data từ buffer ra để sử dụng.
  4. Từ những hành động cơ bản này, bạn có thể thêm các hành động như đặt n data vào hoặc lấy n data ra.

Ta được prototype function như sau, các function này đặt trong file .h luôn nhé, cùng file với Buffer_Struct cho dễ quản lý.

  • int createBuffer(Buffer_Struct *buf,  uint8_t *arr, uint32_t size);
  • int putByteIntoBuffer(Buffer_Struct *buf, uint8_t data);
  • int getByteFromBuffer(Buffer_Struct *buf, uint8_t *data);
  • int putStringIntoBuffer(Buffer_Struct *buf, uint8_t *arr, uint32_t len);
  • int getStringFromBuffer(Buffer_Struct *buf, uint8_t *arr, uint32_t len);

Tiếp theo, ta định nghĩa cho các prototype function này là xong. Bạn tạo 1 file .c và include file .h ở trên.

Hàm khởi tạo, tác dụng là gán các giá trị ban đầu cho buffer.

int createBuffer(Buffer_Struct *buf, uint8_t *arr, uint32_t size)
{
if(buf==NULL || arr==NULL || size<2) return -1; //create failed buf->head=0;
buf->tail=0;
buf->size=size;
buf->arr=arr;
return 0;
}

Bạn thấy ở trên, đã kiểm tra trường hợp khi truyền vào buffer rỗng, arr rỗng hoặc size nhỏ hơn 2 đều bị failed. Nếu không bị các trường hợp nêu trên thì buffer tạo thành công và trả về giá trị là 0.

Tiếp theo là hàm đặt 1 data vào buffer.

int putByteIntoBuffer(Buffer_Struct *buf, uint8_t data)
{
uint32_t tmp=buf->head;
tmp++;
if(tmp>=buf->size)
tmp=0; //reset counter
if(tmp>=buf->tail)
return -1;//buffer full
buf->arr[buf->head]=data;
buf->head=tmp;
return 0;
}

Chúng ta đang làm việc với buffer có dạng liên kết vòng, đầu nối với đuôi, nên khi counter lớn hơn size thì nó reset về 0. Và nếu buffer đầy thì ta cũng không được thêm data vào.

Ta cũng có thể tùy biến với việc đặt n data vào buffer.

int putStringIntoBuffer(Buffer_Struct *buf, uint8_t *arr, uint32_t len)
{
if(len>buf->size)
return -1; //not enough size
for(uint32_t i=0; i<len; i++)
{
putByteIntoBuffer(buf, arr[i]);
}
return 0;
}

Tiếp đến, sau khi đã cất giữ bánh (data), bạn cũng cần lấy ra ăn lúc đói chứ.

int getByteFromBuffer(Buffer_Struct *buf, uint8_t *data)
{
uint32_t tmp=buf->tail;
if(tmp>=buf->head)
return -1;//buffer empty
*data=buf->arr[tmp];
tmp++;
if(tmp>=buf->size)
tmp=0;
buf->tail=tmp;
return 0;
}

Như bạn thấy ở trên, chúng ta cũng cần check buffer có data để lấy không, nếu không có nó sẽ trả về -1, nếu sẽ trả về 0. Lưu ý data mới là biến chứa giá trị thực sự.

Ta mở rộng với get n data.

int getStringFromBuffer(Buffer_Struct *buf, uint8_t *arr, uint32_t len)
{
if(len>buf->size)
return -1;
for(uint32_t i=0; i<len; i++)
{
getByteFromBuffer(buf, arr+i);
}
return 0;
}

Vậy là ta đã xây dựng xong một bộ buffer hoàn chỉnh rồi. Nó sẽ giúp các bạn rất nhiều trong việc truyền nhận data sau này đấy.

Tôi đã hướng dẫn xây dựng buffer rồi, việc sử dụng là ở bạn. Nếu bạn không biết cách sử dụng thì nên ôn lại một tí về C là được thôi.

Chúc bạn thành công!

Cài Đặt Linux Lên BeagleBone Black

bbb

Bạn đang bắt đầu học Linux với BeagleBone Black?
Bạn đang loay hoay cài đặt Linux cho nó mà chưa được?
Bạn vò đầu bức tai vì không biết làm thế nào?

Mình cũng đã từng như thế và mình cũng rất mong muốn sẽ giúp đỡ các bạn trong những bước đi đầu tiên trên con đường học Linux với BBB. Vạn sự khởi đầu nan mà, nhưng gian nan thì đừng có nản nhá.

Đầu tiên là bạn phải có board BBB nhé, 1 thẻ microSD, 1 nguồn 5V-2A.

Let’s start!

Mục tiêu của chúng ta là cài đặt Linux lên BBB từ thẻ microSD nhé.

Nếu bạn đã từng cài Win, bạn có nhớ việc đầu tiên làm là gì không? Đó là tải file .iso, với BBB đó là file .img. Bạn vào trang latest-images để tải file .img về nhé, ở đây tôi sử dụng bone-debian-8.7-iot-armhf-2017-03-19-4gb.img.xz.

Có lẽ lúc bạn xem bài này, đã có phiên bản mới, nhưng nó cũng tương tự thôi.

Bạn cũng cần tải về tool để write file .img này xuống thẻ nhớ. Ở đây, tôi sử dụng Win32DiskImage để write.

Bạn cũng cần cài driver BBB cho máy tính của mình nữa nhé. Bạn có thể tham khảo trên mạng hoặc vào trang này driver BBB và kéo xuống Step 2 nhé.

Bạn cắm thẻ nhớ vào máy tính (thông qua đầu đọc thẻ). Giải nén file .img vừa mới tải về. Mở chương trình Win32DiskImage lên. Sau đó, write file .img xuống thẻ nhớ (bạn tham khảo hướng dẫn sử dụng Win32DiskImage). Thời gian write tùy thuộc vào cấu hình máy tính của bạn, có thể 1 ngày, tôi đùa thôi khoản vài phút là xong.

Sau khi write xong, bạn eject thẻ nhớ khỏi máy (rút ra đúng cách đó mà). Tiếp theo, bạn cắm thẻ nhớ vào BBB, nếu hem biết cắm chổ nào thì kéo lên cái hình ở trên trển nhá.

Công việc sau đây hơi khó một tí nhé. Sử dụng sợi cáp USB cắm 1 đầu vào máy tính, đầu kia chưa cắm vào BBB nhé. Bạn nhấn giữ Boot Button nhé, sau đó cắm đầu còn lại của cáp vào BBB. Đợi 1 tí, bạn sẽ thấy đèn sáng lần lượt từ USR0 sang USR3.

ledBBB.png

Sau khi cả 4 con cùng sáng nó sẽ tắt, sau đó nó sẽ chớp báo hiệu vào chế độ boot (không nhớ con nào chớp nữa nhưng có chơp). Chưa nhả nút Boot ra nhá, phải giữ đến khi cài xong đấy. Tôi đùa thôi, tới đây, bạn có thể buông nút này ra được rồi.

Đến đây là mọi chuyện gần như hoàn tất rồi (nếu board bạn mới mua), nhưng khi bạn khởi động lại mà không cần thẻ nhớ thì vẫn mắc kẹt lại ở hệ điều hành cũ, lý do là bạn chưa flash vào eMMC của BBB.

Để setup tự động flash eMMC khi bật nguồn, bạn phải thêm vài bước nữa, càng ngày độ khó càng tăng lên rồi nhé. Bạn tham khảo trang này Flash eMMC nhé hoặc xem thêm bên dưới.

Bạn đợi lúc, sẽ thấy BBB hiện lên trên PC giống như 1 ổ cứng

img

Tiếp theo, bạn sử dụng Chrome hoặc Firefox để browse đến web server của BBB (IE sẽ không dùng được nhé). Bạn browse đến beaglebone.local hoặc 192.168.7.2.

Bạn kéo xuống và click vào Cloud9 IDE để mở IDE Cloud9 lên. Ở đây, bạn có thể chạy 1 số ví dụ để lấy động lực. Mở file blinked.js lên, click vào Run sẽ thấy 4 led cùng chớp tắt với chu kì 1s, nhấn Stop để dừng. Chơi vậy đủ rồi, mình tiếp tục hoy.

Click vào tab Window chọn New Terminal, bạn sẽ mở 1 cửa sổ terminal để làm việc như 1 hacker í. Nếu có đăng nhập bạn thì id:pass mặc định là [debian:temppwd] nhé. . Khi nhập mật khẩu mà không thấy gì là bình thường nhé, không phải do bàn phím hư đâu, mật khẩu bị ẩn mà.

Bạn nhập vào dòng lệnh:

sudo nano /boot/uEnv.txt

Mật khẩu mặc định là “temppwd” nhé.

Lúc này ta đang mở file uEnv.txt đấy. Bạn sử dụng phím Pn Dn (mũi tên xuống ấy), đến dòng

#cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh

Bạn xóa dấu “#” đi

cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh

Nhấn Ctr+X để thoát, nó sẽ hỏi bạn có lưu hay không, thì nhấn y nhé (chọn yes đó mà), nó sẽ hỏi tiếp là bạn lưu với định dạng file nào thì bạn Enter luôn nhé. Toàn thao tác bằng bàn phím không à, bạn đang là hacker mà. Bây giờ, tiến hành reboot lại, sử dụng command line luôn cho ngầu nào:

sudo reboot

Lúc này BBB sẽ tự động làm tất cả, bạn ngồi chơi thôi, kiên nhẫn nhé. Nếu làm đúng bạn sẽ thấy đèn led blink từ 0-1-2-3-2-1-0-….., nó đang flash file .img đó. Ngồi đợi đi, nó flash khoảng 1 ngày là xong chứ gì, đùa thôi, khoảng vài phút à. Khi nào flash xong, nó sẽ sáng hết 4 led, rồi tự động tắt nguồn. Vậy là bạn đã cài Linux cho BBB thành công rồi.

Cung cấp thêm cho bạn câu lệnh để tắt nguồn cho đúng cách nè:

sudo shutdown -h now

hoặc

sudo poweroff

Trong lần khởi động sau, bạn rút thẻ nhớ ra nhé, BBB sẽ tự boot Linux từ eMMC lên.

Chúc các bạn thành công!