Apr 14, 2013

Macro nho nhỏ hiện các thông báo.


Trong lúc viết đồ án về Chat Reference, mình gặp chút vấn đề về việc xuất các thông báo cho người dùng. Đồ án được thực hiện trên MFC và dùng hàm MessageBox , trong khi đó, lúc lập trình, mình lại thiết kế các module, tức phần bussiness lại thực hiện trên console, dùng hàm printf. Lúc chuyển qua MFC phải chuyển hết các hàm đó ... Vả lại mỗi lần viết hàm lại 1 lần viết chuỗi xuất ra, thành thử nhiều khi không nhất quán.

Macro này giúp giải quyết vấn đề nho nhỏ đó. Đúng ra thì 1 con trỏ hàm, cũng có thể làm được điều này. Nhưng mình lại thích làm trên macro hơn :)) =)). Một vấn đề trong con trỏ hàm là đôi khi các hàm mình cần dùng không cùng chung kiểu khai báo, và như vậy dùng con trỏ hàm sẽ không ổn. Đồng thời việc biến tấu cũng không được gọn.

#define MAX_BUFERROR 255
#define COMMAND_ERROR printf
#define NEWEXCEPTION(mess, code) { \
                        char err[MAX_BUFERROR]; \
                        sprintf(err,mess". CODE: %d.\n", code);\
                        COMMAND_ERROR (err);\
                        fflush(NULL);\
                        }

Chút chú thích cho cái này xíu:

  • MAX_BUFERROR: Độ dài chuỗi tối đã của thông báo
  • COMMAND_ERROR: Tên hàm thực hiện xuất ra chuỗi
  • Yêu cầu phải có thư viện stdio.h cho macro này

Apr 11, 2013

iTools: Phần mềm quản lí iPhone và các thiết bị Apple

Trong một ngày đẹp trời ngồi tìm cách chép nhạc, phim, video và tùy chỉnh các thông tin trên iPhone, mình đã tìm được phần mềm này. Cứu cánh cho các vấn đề nan giải.

Chép nhạc, phim, video sang Iphone

Ưu điểm

  1. Dễ sử dụng, miễn phí và thân thiện với người dùng
  2. Hỗ trợ đầy đủ các tính năng, cập nhật các phiên bản mới của Apple
  3. Quản lí app, file hệ thống, thông tin, các tập tin đa phương tiện dễ dàng và tiện dụng, không cần phải kết nối ITunes
  4. Chép nhạc, phim, video, cũng như xóa các tập tin này trong iPhone một cách dễ dàng và tiện dụng
  5. Tương thích với nhiều phiên bản Windows: Windows 7, Windows 8..

Lưu ý: Phần mềm yêu cầu phải có iTunes cài trong máy. Khi kết nối sẽ tự động sync với thiết bị mà không bị mất dữ liệu.

Download here

Apr 5, 2013

Hàm strtok và những rắc rối xung quanh


Thật bất ngờ và tình cờ vì phải đụng đến em này lúc train thi Thách Thức. Và cũng tò mò là vì sao em này có cách dùng lạ đến vậy. Nhưng trước tiên là một số thông tin hấp dẫn đã.

Cú pháp:


char* strtok ( char *str, const char *delimters); 
 
 

Công dụng: Tách chuỗi str thành các chuỗi con. Các kí tự ngăn cách được định nghĩa trong chuỗi delimters.

Tham số:

  • str: chuỗi cần tách.
  • delimters: chuỗi chứ các kí tự ngăn cách

Các sử dụng: để lấy từ phẩn từ sau khi được cắt bị kí tự phân chia. Ta sử dụng đoạn code sau:

pch = strtok (str," ,.-");
while (pch != NULL)
{
  // Phần tử lấy ra là pch pch
  // Xử lý các thao tác trên pch
 pch = strtok (NULL, " ,.-");
}
return 0;

Nhiều người sẽ thắc mắc: đoạn mã strtok(NULL, " ,.-") nghĩa là gì. Nguyên nhân là trong hàm strtok sẽ tạo 1 biến static là char* - ta tạm gọi là last. Ban đầu nó sẽ được gắn bằng NULL. Sau lần duyệt đầu tiên, last sẽ có giá trị là địa chỉ hiện thời của phần tử đã lấy được. Khi chạy đến hàm strtok thứ 2 nó kiểm tra tham số đầu vào có phải là NULL không. Nếu phải thì nó lấy địa chỉ của chuỗi đem cắt gắn bằng giá trị mà last đang giữ.

Tham khảo:

  1. Source code hàm strtok của Microsoft
  2. Source code hàm strtok của Apple.

Lưu ý: vì hàm này tạo 1 biến static tạm để giữ giá trị vừa cắt nên không dùng được cho xử lý đa nhiệm.

Mar 31, 2013

Lập trình syscall trên nachos

Trong file hướng dẫn của thầy không thực sự cụ thể, và như vậy rất khó cho mọi người thực hành theo, vậy mình sẽ viết lại các qui trình một chút_
Một chút tìm hiểu về quá trình thực thi 1 hàm
Qui trình thực thi các interrupt sẽ được đề cập sau
  1. Xây dựng trong kernel space
    Để xác định user đang gọi cái interrupt nào. Ta cho nó 1 định danh là 1 số nào đó. Khi kernel nhận được số đó thì hiểu là user yêu cầu chuyện gì.
    Ví dụ: Nếu user đưa vô số 11 tức là yêu cầu đọc 1 số nguyên từ console.
  2. Tạo macro:
    Để đỡ phải quên trong việc lập trình, ta sẽ define số đó thành 1 macro.
    Trong syscall.h:
    define SC_ReadInt 11
    Khai báo interface cho end-user:
    Cũng trong syscall.h, ta tạo một hàm để người dùng (end-user) giao tiếp với hệ điều hành, ở đây ta khai báo hàm ReadInt();
    int ReadInt();

    Định nghĩa hàm trong file assembler.
    Khi người dùng gửi đến 1 thông điệp, ví dụ như “đọc 1 số từ console”, đến với hệ điều hành – lúc này hiểu thông điệp là 11 chẳng hạn. Để hệ điều hành nhận được số 11 đó và truyền đến chỗ xử lý các thông điệp, ta cần pass giá trị này qua. Giống như gọi 1 hàm xxx(11) vậy. Trong nachos, công việc này tức là truyền 11 vào biến $2 được qui định trước đó và gọi system call.

    Ta mở các file sau: code/test/start.c và code/test/start.s:
    .globl ReadInt
    .ent ReadInt
    ReadInt:
        addiu $2, $0, SC_ReadInt
        syscall
        j $31
        .end ReadInt
    

    Như vậy, thông điệp “đọc 1 số từ console” đã đến tai hệ điều hành. Giờ là lúc bắt tay vào xử lý công việc đó. Và vì đây là software interrupts, hay còn gọi là 1 exceptions. Nên dĩ nhiên, ta sẽ thêm mã vào file usrprog/exceptions.cc
    ///....
    switch(which)
    {
        case SystemcallException:
            switch(type)
            {
                case SC_ReadInt:
                // Đoạn mã thực thi
                break;
                // Các xử lý khác ...
            }
            / Tăng biến pc lên 1 đơn vị
            machine->Registers[PrevPCReg] = machine->Registers[PCReg];
            machine->Registers[PCReg] = machine->Registers[NextPCReg];
            machine->Registers[NextPCReg] += 4;  
    }
    ///....
    
    
  3. Một số lớp và phương thức được thêm vào trong đồ án:
    1. SynchConsole
      Được cài đặt ở thư mục threads/ giúp truy xuất giữa console và người dùng.
      Trong file threads/system.h, phần định nghĩa macro USER_PROGRAM ta include header file của SynchConsole. Đồng thời khai báo extern cho biến gSynchConsole;
      $ifdef USER_PROGRAM
      #include "synchcons.h"
      extern SynchConsole *gSynchConsole;
      #endif
      Trong file threads/system.cc, cũng trong phần khai báo macro USER_PROGRAM ta khai báo biến gSynchConsole (chỉ khai báo, không có khóa extern).
    2. User2System và System2User

      Mã code của 2 phương thức này được trình bày ở link này: Click vào đây

      Hai hàm này sẽ trở thành phương thức public trong lớp Machine. Khai báo hàm nằm ở machine/machine.h và phần định nghĩa sẽ nằm ở machine/machine.cc hoặc có thể là trong translate.cc. Mình nghĩ là nên đặt vào trong translate.cc hơn, vì nó phần nào thể hiện bản chất: các phương thức liên quan đến vùng nhớ sẽ được đặt ở đó.
  4. Test hàm và chạy thử nghiệm
    Trong thư mục test/, ta tạo một tập tin .c để kiểm tra tính đúng đắn của exception vừa viết. Đó là gọi hàm đó theo tham số đã đề xuất.
    Cấu hình Makefile:
    Để có thể sử dụng lớp SynchConsole, ta mở file Makefile.common và thêm các thông số sau:
    • Tại THREAD_H : ‘../threads/synchcons.h’
    • Tại THREAD_C : ‘../threads/synchcons.cc’
    • Tại THREAD_O : ‘../threads/synchcons.o’
      Cấu hình file test
      Ví dụ ta muốn chạy đoạn mã test.c, qui trình biên dịch và chạy như sau:
    • Trong file test/Makefile:
      all: ... test
      Thêm vào cuối file
      test.o: test.c
          $(CC) $(CFLAGS) -c test.c
      test: test.o test.o
          $(LD) $(LDFLAGS) start.o test.o -o test.coff
          ../bin/coff2noff test.coff test
      
      

      Sau khi make xong, ta chạy lệnh ./usrprog/nachos -rs 1023 -x [Đường dẫn đến file thực thi].

Mar 2, 2013

Cấu hình giao diện cho Eclipse trên Linux

Trong Linux, giao diện của Eclipse có phần bất tiện vì khoảng trắng giữa các icon khá lớn, khiến cho không gian trở nên nhỏ đi. Điều đó gây ra sự bất tiện lớn khi làm việc


Giải pháp cho vấn đề đó như sau:
  • Trong thư mục ~/ mở file .gtkrc-2.0 và chép đoạn mã sau:
    style "gtkcompact" {
     font_name="Sans 8"
     GtkButton::default_border={0,0,0,0}
     GtkButton::default_outside_border={0,0,0,0}
     GtkButtonBox::child_min_width=0
     GtkButtonBox::child_min_heigth=0
     GtkButtonBox::child_internal_pad_x=0
     GtkButtonBox::child_internal_pad_y=0
     GtkMenu::vertical-padding=1
     GtkMenuBar::internal_padding=0
     GtkMenuItem::horizontal_padding=4
     GtkToolbar::internal-padding=0
     GtkToolbar::space-size=0
     GtkOptionMenu::indicator_size=0
     GtkOptionMenu::indicator_spacing=0
     GtkPaned::handle_size=4
     GtkRange::trough_border=0
     GtkRange::stepper_spacing=0
     GtkScale::value_spacing=0
     GtkScrolledWindow::scrollbar_spacing=0
     GtkExpander::expander_size=10
     GtkExpander::expander_spacing=0
     GtkTreeView::vertical-separator=0
     GtkTreeView::horizontal-separator=0
     GtkTreeView::expander-size=8
     GtkTreeView::fixed-height-mode=TRUE
     GtkWidget::focus_padding=0
     }
    class "GtkWidget" style "gtkcompact"
    style "gtkcompactextra" {
     xthickness=0
     ythickness=0
    }
    class "GtkButton" style "gtkcompactextra"
    class "GtkToolbar" style "gtkcompactextra"
    class "GtkPaned" style "gtkcompactextra"
    
  • Lưu file này lại và mở lại Eclipse. Lưu ý: Các chương trình khác dùng giao diện gtk cũng bị ảnh hưởng
Kết quả thu được:

Về vấn đề autocomplete không hoạt động.Giải quyết: Nhấn Alt + W + P. Chọn C/C++ - Editor - Content Assist -- Advanced và tick chọn hết. Về vấn đề tooltip bị nền màu đen hoặc khung Proposals không nhìn được: chọn giao diện hệ thống khác ( gtk theme), hoặc phải cấu hình lại giao diện đó

Dec 19, 2012

Sự khác biệt về hàm main của C và C++

Thoạt đầu tưởng chừng như không có sự khác biệt giữa 2 ngôn ngữ với hàm 'main': hàm đặc biệt quan trọng trong chương trình. Nhưng thưc tế lại khác xíu.
Cho 2 đoạn mã sau.
Đoạn 1: Viết bằng c:
#include <stdio.h>
float main(int a, int b, int c)
{
    printf("Chao cac ban\n");
}
Đoạn 2: Viết bằng cpp:
#include <iostream>
using namespace std;
int main( int n, char x, float t) 
{
    cout << "Chao cac ban" <<endl;
    return 0;
}
Cả 2 đoạn mã điều chạy được, tuy nhiên nếu compile đoạn mã cpp sẽ dính 2 cái Warning. Còn đối với c thì không có gì. Điều thú vị hơn là nếu trong đoạn mã cpp ta thay đổi kiểu trả về của 'main' từ 'int' sang 'float' thì lại dính error.
Đây là lí do:
  • Trong C, nó chỉ yêu cầu tồn tại một hàm tên 'main', vậy là đủ, nó không quan tâm đến chuyện tham số đầu vào hay kết quả trả về.
  • Trong C++, nó khuyến cáo sử dụng 2 mẫu:
    int main(int argc, char** argv); // hoặc
    int main() //
Nếu không rơi vào 2 trường hợp này: thay đổi số lượng tham số sẽ gây warning, còn thay đổi kiểu trả về gây ra error.

Dec 18, 2012

Giải quyết vấn đề laptop nóng và hao pin khi dùng Linux

Một trong những vấn đề khá đau đầu khi sử dụng Linux trên laptop đó là hiện tượng nóng máy và pin xài không lâu. Qua một năm ngồi mày mò, chinh chiến, làm đủ thứ trò đồi bại với cái máy, cuối cùng mình cũng tìm ra được một số giải pháp xử lý vấn đề này.
Bài viết này tập hợp các thủ thuật, phương pháp nhằm giải quyết các vấn đề sau trên linux
  1. Laptop quá nóng khi sử dụng trên Linux.
  2. Thời lượng dùng pin trên Linux quá ngắn.
  3. Chế độ tiết kiệm pin của Linux không ổn định.

1. Sử dụng các tools:
  1. PowerTOP:Một ứng dụng được viết của Intel giúp giải quyết các vấn đề về sử dụng tài nguyên trên Linux. Khá hay dành cho máy nào dành kiến trức Intel.
  2. cpufrequtils:Quản lí tài nguyên CPU.
  3. pm-utils: Xem hướng dẫn chi tiết ở đây: Pm-utils ArchWiki
  4. lm_sensors: Cách dùng khá đơn giản. Chỉ việc tải về và chạy lệnh "sensors-detect" rồi nhấn 'y' mỗi khi chương trình thông báo là xong.
  5. laptop-mode-tools: Hướng dẫn sử dụng https://wiki.archlinux.org/index.php/Laptop_Mode_Tools. Đây là chương trình khá hiệu quả và có các tùy chỉnh rất phong phú.
  6. powersave: Tổng hợp các script để mở rộng khả năng dùng pin của Linux. Trong trang git của tác giả đã có hướng dẫn khá chi tiết và cụ thể.
2. Tắt card rời đối với card Radeon. Mở file /etc/fstab và gõ đoạn sau:
debugfs /sys/kernel/debug debugfs 0 0
Dùng một trình soạn thảo bất kì để mở file /etc/modprobe.d/blacklist.conf thêm vào cuối file dòng sau:
blacklist radeon
Sau đó mở file /etc/rc.local ở cuối file thêm vào dòng sau:
modprobe radeon
echo OFF > /sys/kernel/debug/vgaswitcheroo/switch
exit 0

Đây là một giải pháp cực kì hiệu quả, giải quyết được vấn đề nóng máy, tốn pin, chạy không ổn định bên Linux. Và nếu không cần đến quá nhiều tài nguyên bên card đồ họa rời, thì đây là 1 thủ thuật rất nên sử dụng. Phương pháp chuyển đổi giữa 2 chế độ card đồ họa được gọi là "Hybrid graphics". Đây là 1 tài liệu rất hay về chủ đề này: link đây. Trong đó có cả cách tắt card ATI và NVIDIA.

3.Các biện pháp khác. - Giảm nguồn sáng của laptop.
- Để làm mát laptop có thể dùng quạt tản nhiệt. Loại từ 100k đến vài triệu tùy vào hầu bao.
- Dùng một trình soạn thảo bất kì mở file /etc/default/grub tìm đến dòng GRUB_CMDLINE_LINUX_DEFAULT và sửa thành:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash pcie_aspm=force i915.i915_enable_rc6=1 i915.i915_enable_fbc=1"
Sau đó ta gõ lệnh sau để tùy chỉnh lại grub:

sudo grub-mkconfig -o /boot/grub/grub.cfg

- Đối với các sản phẩm của Dell. Vào Ubuntu Software Centre hoặc các package manager đối với các bản Linux khác và search keyword là dell, trong phần technical item cài đăt các gõi hỗ trợ laptop của hãng này. Điển hình có gói i8kutils, aircraft-manager...

- Tắt bluetooth: Mở /etc/rc.local và thêm dòng sau:
rfkill block bluetooth
- Cập nhật thường xuyên các driver của hệ thống. Nâng cấp các phiên bản linux mới để fix các bugs cũng như cải thiện tốc độ.
4. Nguồn tham khảo:

Dec 14, 2012

Hướng dẫn khôi phục GRUB 2 sau khi cài Windows

Thông thường, khi cài Windows trước rồi mới cài Linux thì việc GRUB tự động cấu hình menu boot là chuyện không có gì phải lo lắng. Tuy nhiên, trong một số trường hợp, ta cài Linux trước, cài Windows sau, và dĩ nhiên menu boot bên Windows không nhận diện được Linux :( . Cài mới lại Linux rất tốn công và không đáng để làm vậy [Thực tế nho nhỏ là gần 1 năm mình đã dùng cách ấy].
Tutorial sau sẽ hướng dẫn bạn khôi phục lại GRUB2, đồng thời có thể boot được vào cả 2 HĐH.

Công cụ:
- Hệ điều hành Linux, bản distro mình dùng là Ubuntu.
- 1 cái USB hoặc đĩa cài đặt Ubuntu.

B1. Dùng USB hoặc CD chạy live.
B2. Ctrl + Alt + T hoặc tìm chương trình để mở shell command.
B3. Nhấn lệnh "sudo fdisk -l" để xem danh sách các phân vùng trong ổ đĩa. Đồng thời xác định ổ đĩa chứa Linux.
Như ta thấy trong hình mình họa, đĩa cứng được xác định ở /dev/sda và phân vùng chứa hệ điều hành Linux là /dev/sda2
B4. Gõ lần lượt các lệnh sau:
sudo mount /dev/sdx# /mnt  # x# là phân vùng chứa hđh Linux
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo cp /etc/resolv.conf /mnt/etc/resolv.conf
sudo chroot /mnt
sudo grub-install --recheck /dev/sdx  # x là ổ đĩa cần tạo boot menu
sudo reboot
B5. Rút USB hoặc đĩa CD và vào bản Linux trên máy tính.
B6. Mở terminal và gõ lệnh "sudo update-grub" để cập nhật lại grub.
Vậy là xong, giờ có thể dùng song song 2 hệ điều hành.
Nguồn: http://www.lancelhoff.com/restore-grub2-after-installing-windows/
P/s: Lâu lắm rồi mới viết blog, trình có kém đi một chút