目前分類:軟體技術 (60)

瀏覽方式: 標題列表 簡短摘要

 

我測試了可以用 ^^

 

看到論壇上有人強調存檔要存成 utf8 with bom 的編碼
 
 
最近因為一些需求,湊巧看到 autohotkey 能解決 於是這幾天就開始學習它了 但這兩天在用 hot strings 送出中文時一直會亂碼,很挫折 本來想找找網路上寫的函式,像是 utf8 big5 轉來轉去、或放到剪貼簿之類的解法 但不是不成功,不然就還是會亂碼 ... orz 正想說放棄的時候,看到論壇上有人強調存檔要存成 utf8 with bom 的編碼 ( 連結: https://autohotkey.com/boards/viewtopic.php?f=29&t=4276  https://autohotkey.com/boards/viewtopic.php?t=4292 ) 嘗試之後就成功了! 因為在版上好像沒提到這個解法,所以來分享一下

mybeauty 發表在 痞客邦 留言(0) 人氣()

新電腦的source insight在外接螢幕上很模糊,但是用Chrome又很正常。

試一下很久,下面的解法有效。

要單獨為source insight做設定。

 

Solution 2

If you want scale the text, you can do but you must disable the display scaling on high DPI for each app who doesn't display correctly. To do that, You must find the exe of the application. Tips : to find easily the exe, right click on the app => properties => Open file location.

Do the following:

  • on the exe, right click
  • troubleshoot compatiblity
  • Troubleshoot program (second option) =>
  • Check "The program open but doesn't display correctly"
  • Next
  • Check "Program does not display properly when large scale font settings are selected"
  • Test the program...
  • Next
  • Yes, save these settings for this program

If you want to do, you can use The process explorer and add the column dpi aware to help you. This tools is avaible on the Microsoft sysinternals webiste.

 

來源

https://superuser.com/questions/1287429/how-to-fix-blurry-text-in-windows-10-with-multiple-monitors

 

mybeauty 發表在 痞客邦 留言(0) 人氣()

我有個軟體視窗,每次打開後就飄到另一個螢幕。

但是我並沒有接那個螢幕啊  orz

 

上網找到解法了。轉貼如下

中文

Windows 10 的視窗不見了

Windows 10 的視窗不見了

 

Windows 10 執行程式之後,卻看不到視窗,但是,底下的工作bar卻有出現,Alt+TAB也可以看到應用程式在執行…

只好請出 Google 大神,找到 Microsoft 網站上的解答:

https://answers.microsoft.com/zh-hant/windows/forum/windows_10-start/%E6%A1%8C%E9%9D%A2%E4%B8%8D%E8%A6%8B%E4%BA%86/d3e62d0c-c178-4d21-969c-94e34d6ab1a3?auth=1

結果真是令人失望,還好這篇有解法:

http://ilyvonne.pixnet.net/blog/post/26863403-視窗跑到螢幕外-該怎麼辦?

整理一下步驟:

1.從底下的工作bar,點選到應用程式

2.【Alt+space】

3.【移動(M)】

4.使用上下左右的方向鍵,或是 mouse,將視窗【拖】回正常的位置

謎之音…好爛的 bug !

 

英文
 

A Window is Not Visible: How to Move Off-Screen Windows Back into View

A Window is Not Visible: How to Move Off-Screen Windows Back into View

Every once-in-a-while we receive a call from a client who launched an application, but the application didn’t show up on their screen. They confirmed in the taskbar that the application was running. However, the window was not visible on their screen.

If you use a secondary monitor, and/or if you operate within a remote desktop environment, you may have experienced this issue. When a secondary monitor is disconnected, or the display settings are altered, sometimes applications will still operate as if nothing had changed with the monitor or display. The window opens in an “imaginary” place off to the side, where that monitor used to be.

Here are simple steps to move an off-screen window back to your screen:

1. Make sure the application is selected (choose it in the taskbar, or use the ALT-TAB keys to select it).

2. Type and hold down ALT-SPACE, then type M. (IMPORTANT NOTE: If you’re working on a remote desktop or cloud, use ALT-DELETE instead if ALT-SPACE.)

3. Your mouse pointer will change to have 4 arrows.

4. Use the arrow keys on your keyboard to move the window back onto your screen.

Some tips to avoid this happening in the first place:
— Move open windows to your primary monitor before disconnecting the secondary monitor.
— If shutting down, do so before disconnecting the secondary monitor.
— When working in a remote desktop, do not disconnect from the remote desktop using the “X” key at the top. Instead, close all open applications, and then go to the Start menu and select “Log Out”. (This is a good practice in general, as failure to log out of a remote session could cause several other problems.)

mybeauty 發表在 痞客邦 留言(0) 人氣()

 

面試官心得-1 (軟體工程師)

 

我一直想要把我的面試心得分享給網友,我貼在我的部落格裡面,也許能看到的人不多。

不過我想貼在這裡的自由度比較高,網友若有任何問題也可以問我,

不過我是一個很忙的人,可能也不太有時間回覆大家。

 

我當面試官大概有5年多的經驗,每年應該會面試到20個人左右。第一篇先寫個總論吧。


 

***剛出社會的新鮮人

 

首先,鼓勵大家在學校要好好學習。對我們出社會很久的人來說,剛從學校畢業的新鮮人,所學會的東西真的非常的少。但是如果你在研究所學的很特別,對我們業界有即戰力,是很大的加分。

 

如果你真的什麼都不會,那也沒有關係,有些好心的主管,會當你是一張白紙開始訓練,但是我覺得這個機會不是很多。一般來說,小公司比較有可能,因為小公司並不好找人,但是大公司可以挑選的人很多。

 

ptt上很多人,第一份工作決定了你後來的工作,我也是這麼認為。例如你一開始就做測試, 當你要換第二份工作,我相信有很多測試的工作會找你。在電子業界來說,不只是隔行如隔山,即使軟體業界,所需要的知識差異也非常大。

 

第一份工作,我覺得是以磨練工作技能為主,能不能進大公司要看運氣,如果又是大公司又是自己的興趣最好,可遇而不可求。

 

***年輕工程師

 

前一份工作的經驗,大概就會決定你下一份工作要做什麼。通常面試主管,會找有相關經驗的人。有時候扯的上一點點邊,就可以了,所以多學多看是很重要的,哪怕就這麼一點點經驗,剛好是下一份工作所需要的。例如,我要找一個會寫APP的工程師,雖然他只曾經寫過很簡單的一個App,但是我覺得他對物件導向APP開發有基礎的認識。我可以進來再訓練他。


 

***資深的工程師

 

我這裡定義的資深,大概是年紀在40歲以上。40歲以上的工程師會不會很難找工作呢?我相信很多人都有這個疑問,以我的觀點,40歲到45歲的工程師,如果技術很好,找新工作並不難。我也曾經錄用過50歲的工程師,不過他是同事介紹的。

 

二三十年前,很多人都說,希望在科技界撈一筆,然後就退休或是做其他的工作。我今日來看, 並不容易達成,我的同學們也都在上班,目前還沒看到誰真正去退休了。

 

很多人說寫code能不能寫到一輩子,我覺得至少寫到50歲沒有問題。其實學得越多,學習會越快。有一個重點是,我覺得對工作要有興趣,因為做研發工作普遍來說工時很長,如果沒有興趣,只會自己覺得被困在牢籠裡,長期來說並不是很好。

 

如果我要任用40歲以上的工程師,只有兩種選擇,第一個是他的技術很好,第二個是他能夠當主管能帶人。 我認為並不是每一個人,都要去追求當主管。軟體工程師的價值還是在技術,即使是軟體主管,仍然要有一定的技術底子。我曾經面試過兩位軟體主管,我感覺應徵者沒有霸氣,沒有那種會讓人想追隨的感覺,可能他只是因為待的久,所以當上了主管。


 

***坊間的軟體培訓課程有用嗎

我覺得多少有加分,但是這仍然只是學習的程度。最好的狀況是曾經在前份工作有做過類似的專案,學習與商業應用仍有很大的不同,商業應用上要處理很多問題。比方說是防呆, 比方說硬體速度太慢,或者是,在公司的環境下,實作的速度會比較快,除了軟體功力之外,也會訓練抗壓性,和解題的速度。

 

我個人是以在前份工作做過類似的專案為優先。學校環境, 也有過於理想化的情況。我們在業界,需要的是可維護性,可執行性,還有就是速度要很快。有時候並不一定做得很完美,完美可能也不存在於真正的軟體產品當中。我們看到市面上的軟體很完美,那是因為已經經歷過好幾代的開發以及維護,第一版的軟體只要架構有設計好,經過一定的測試就可以了。要達到極穩定需要一段時間。完成之後,也需要一段時間,讓客戶修改少部分的行為。


 

***解不出來怎麼辦

曾經有幾位面試者,問我如果bug解不出來怎麼辦。當然這就是我們做leader要去克服的問題。一般來說,應該沒有解不出來的bug,只要有原始碼,都能夠一行一行的去找。但是真實的情況,是時間非常的不夠,每一個公司給RD的時間都非常的少,所以要訓練自己的解題能力。 多唸書多寫程式,會有很大的幫助。當然, 和同事討論更快。


 

***工作中的難題

我覺得工作裡比較困難的,反而不是程式本身,有一種情況是溝通問題,例如你的程式架構在別人的基礎上,需要別人提供API的修改,但是別人不願意改。另一種情況是時間太少,比方說要三個月才能夠完成的工作,壓縮到只有一個月。以上這兩種情況,在我們公司幾乎天天都會發生,雖然都是管理的問題,我都會告知主管,但是往往也沒有其他方法。

 

我們很難要求在完美的情況下工作,比方說別人交給你的時間都是準時的,如果有這樣子的工作環境,那表示你交給別人的時間也是準時的,那一定是一個要求很高的公司。在不完美的環境下,要盡力的把事情做好,這就是我每天的工作挑戰。


 

***不招人忌是庸才

最近體會到的事情,是就算做的最好, 還是會有很多的困難和挫折。比方說會受到其他部門的攻擊。有句話說, 不遭人忌是庸才,我目前還沒有想到很好的方法可以解決這種問題,其實我已經很低調,還是沒有辦法避免。只能放寬心去上班,工作還是以實力為主。









 

mybeauty 發表在 痞客邦 留言(2) 人氣()

裝了一下,速度意外的好

太棒了

 

 

mybeauty 發表在 痞客邦 留言(0) 人氣()

這一篇寫的很好很簡單,抄錄如下

 

 

由於有時會將資訊儲存下來,等著下次程式開啟時使用。以下教學怎麼記錄資訊在ini檔裡以及讀取ini檔。

一開始先將目前程式位置儲存在QStringpath裡

#include<QSettings>

QString path = QApplication::applicationDirPath();

設定寫入的ini檔名

path += "\\Information.ini";

設定ini格式以及群組名稱和資料

QSettingssettings(path,QSettings::IniFormat);
mySettings.setIniCodec("UTF-8");
mySettings.beginGroup("Group1");
 
mySettings.setValue("Value",1);

上述步驟完成後,會在與程式相同資料夾下產生一個名為Information的ini檔
內容如下

[Group1]
Value=1

接著我們試著讀取ini檔

QString path = QApplication::applicationDirPath();
path += "\\Information.ini";
QSettings settings(path,QSettings::IniFormat);
settings.beginGroup("Group1");
int nValue=settings.value("Value").toInt();

nValue值即得獲得1值。

 

http://body0314.pixnet.net/blog/post/208180585-qt-%E8%AE%80%E5%AF%ABini%E6%AA%94

mybeauty 發表在 痞客邦 留言(0) 人氣()

 

因為實在是寫的太好了,所以我貼過來

 

一秒看破 static

 

static 靜態 是個很奇妙的 關鍵字

早在 哈囉,世界 的時候就看到 static void Main() 這個 加了 static 關鍵字的方法

但是在真正了解 static 的意義卻又是很久以後的事了

 

 

最基本 也大家都知道的是

靜態的成員 不需要實體(Instance) 就能進行訪問

非靜態的成員 必須 new 一個 實體(Instance) 才能進行訪問

但這不算解釋 反而是混亂的開始

在單一使用者 單一執行 簡單功能 的情況下 這2種寫法 跑的結果一模一樣

這時就會有人覺得 那就都用靜態就好了呀 不用 new 多方便

但是隨即就嚐到苦頭 因為 靜態並非 沒有實體 而是只有一個實體 在程式執行之初就建立 並佔用記憶體位置 而且一直存在

當程式用上一堆靜態成員的時候 就造成不必要的記憶體浪費

但是現在硬體都不錯 也許這隱藏殺機不是那麼明顯 但是另一個問題就頭大囉

那就是牽一髮而動全身 靜態成員是唯一的 只要是宣告成 static 且同名的成員 都是共用一區記憶體位置

即使你這麼做

雖然 new 了三個物件 但是只要設定其中一個 其他三個 也會跟著改變

 

 

 

 

相對於 變數 屬性 這種顯而易見的差異 靜態方法 跟 非靜態方法 就顯得有些曖昧

靜態方法 屬於 類別所有

非靜態方法 屬於 實體所有

 

靜態方法 只能以類別名叫用 即使是 非靜態類別

非靜態方法 只能以實體叫用 所以 靜態類別 內無法有 非靜態方法 (靜態類別內一切都是靜態的)

從執行效能來看 靜態方法 比較好 因為是共用的 省去建立 跟 銷毀 物件的效能

但是也代表 靜態方法 永遠存在 不論這方法 會不會被執行

 

即使這樣說也很難判斷到底何時要用 靜態方法 何時不用

但是如果從物件導向的角度 - 封裝 出發 就很明確

 

例如一個公開的類別的 公開靜態方法 跟 公開非靜態方法 就有意義上的不同

公開的類別的公開靜態方法 即使不屬於此類別 也能叫用 因為都是公開的

公開的類別的公開非靜態方法 卻只能是 屬於此類別的 實體 才能叫用

 

例如一個公開類別名叫 男人 有個方法叫 站著小便

如果他是 非靜態方法 那麼可以確定 只有男人可以站著小便

如果他是 靜態方法 那就好玩了 就算是女人類別 也能 執行 男人.站著小便() 方法

好吧我知道這例子很鳥 或許真的有女人喜歡站著小便?!

 

那再舉一例吧 跟錢有關的 都比較有深刻體驗

 

例如一個公開類別名叫 我 有個方法叫 花光我的積蓄當月光仙子

如果他是 非靜態方法 那麼可以確定 只有我可以花光我的積蓄當月光仙子

如果他是 靜態方法 那就好玩了 就算是路人類別 也能 執行 我.花光我的積蓄當月光仙子() 方法

然後我的薪水就被花光了 而且花光的人 還不是我

 

WTF,怎麼每個聽起來都很可怕 那又什麼時候該用 靜態方法?

 

例如一個公開類別名叫 學生 有個方法叫 作弊

如果他是 靜態方法 那真棒 誰都可以幫助學生作弊

如果他是 非靜態方法 那有點糟 學生只能自立自強 備妥小抄望遠鏡

 

好吧我知道這例子很鳥 鼓吹作弊 違反社會善良風俗

 

例如一個公開類別名叫 我 有個方法叫 叫我起床

如果他是 靜態方法 那真棒 誰都可以叫我起床

如果他是 非靜態方法 那有點糟 只有我可以叫我自己起床 沒人幫的了我

 

 

 

 

 

 

 

 

 

 

 

原始網頁

http://weisnote.blogspot.com/2012/08/static.html

 

 

mybeauty 發表在 痞客邦 留言(0) 人氣()

20180417-125700
 
 

叫出工作管理員,把explorer.exe結束掉,然後再到工作管理員的 [檔案]=>[新工作]

輸入explorer,然後按[確定],就可以恢復正常了

mybeauty 發表在 痞客邦 留言(0) 人氣()

 

來源

https://stackoverflow.com/questions/8158007/how-to-jump-the-program-execution-to-a-specific-address-in-c

 

Inline assembly might be the easiest and most "elegant" solution, although doing this is highly unusual, unless you are writing a debugger or some specialized introspective system.

Another option might be to declare a pointer to a void function (void (*foo)(void)), then set the pointer to contain your address, and then invoke it:

void (*foo)(void) = 0x12345678;
foo();

There will be things pushed on the stack since the compiler thinks you are doing a subroutine call, but since you don't care about returning, this might work.

shareimprove this answer

mybeauty 發表在 痞客邦 留言(0) 人氣()

Linux Device Driver - IOCTL (copy_to_user & copy_from_user)

 
在 linux/include/linux/fs.h 中定義許多file operation能用的handler
這一次我針對的是 read、ioctl做練習
file operation中沒實做到的handler會被定義成NULL
這一支程式會先得到來自kernel的回應,接著kernel 換更改指定的數字

先大概說一下主要概念
我要先寫一個mydev.c 當作 driver
執行完make 之後 就把 mydev.ko 加入到 kernel中
此時的 mydev.ko 就是模組, 一個在kernel中的模組了
那要如何與此模組互動呢?
我要再寫一個 test_mydev.c 當作 user
直接把他 gcc 產生執行檔 再指定我要跟mydev 模組溝通

首先先來看 ioc.h
這裡定義了 user 能夠透過 ioctl 傳達的指令
IOC_MAGIC 是device 的 major number , 而我定義其major number為 k
每一個裝置都有其major number 與 minor number
接著我設置 SETNUM  GETNUM  XNUM 3種指令
_IOW  _IOR  _IOWR 是 kernel 的巨集 , 我們用這3個巨集來定義我們的命令要做哪些事
各聚集裡的1,2,3 是自訂的minor number

#ifndef IOC_H
#define IOC_H

#define IOC_MAGIC 'k'
#define SETNUM _IOW(IOC_MAGIC, 1 , int)
#define GETNUM _IOR(IOC_MAGIC, 2 , int)
#define XNUM _IOWR(IOC_MAGIC,3 , int)
#define IOC_MAXNR 3

#endif



接著看到最主要的 driver code : mydev.c
在file operations 中定義了我自訂的操作函數
dev_open : 在user open  device file 時會被呼叫
dev_close : 在user close device file 時會被呼叫
dev_ioctl  :  switch case 中寫了各種command該執行的動作
         若user 呼叫 ioctl 時傳入 SETNUM 則 driver 會將傳入的資料(args)取出,並指定給val 變數
         若user 呼叫 ioctl 時傳入 GETNUM 則 driver 會將val 變數傳出(args)
         若user 呼叫 ioctl 時傳入XNUM 則 driver 會將 user 輸入的數值指派給val變數達到更改資料
         的目的
         (因為user space 與 kernel space 儲存data的空間不同, 因此要用 copy_to_user 與
         copy_from_user來轉遞資料)
dev_read : user 呼叫 read時會被呼叫, 我在這裡放了一個hello字串, kernel會利用copy_to_user 傳到
                 buffer中給user
dev_write: 我在這裡沒用到
init_modules:  程式進入點 , 建立裝置並註冊到kernel
exit_modules: 程式結束 , 移除裝置

#include <linux/init.h>
#include <linux/module.h>

#include <linux/fs.h> //chrdev
#include <linux/cdev.h> //cdev_add() / cdev_del()

#include <asm/uaccess.h> //copy_*_user()

#include "ioc.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("IRENE 2013/09/01");
#define DEV_BUFSIZE 1024

static int dev_major;
static int dev_minor;
struct cdev *dev_cdevp = NULL;
static int dev_open(struct inode*, struct file*);
static int dev_release(struct inode*, struct file*);
static int dev_ioctl(struct inode*, struct file*, unsigned int, unsigned long);
ssize_t dev_read(struct file*, char __user*, size_t, loff_t*);
ssize_t dev_write(struct file*, char __user*, size_t, loff_t*);
static void __exit exit_modules(void);

//Functions on the right side are the handler we just defined
struct file_operations dev_fops = {
   .owner = THIS_MODULE,
   .open = dev_open,
   .release= dev_release,
   .ioctl = dev_ioctl,
   .read = dev_read,
   .write = dev_write
};


// dev_open will be Called when user open the device file
static int dev_open(struct inode *inode, struct file *filp)
{
       printk("%s():\n",__FUNCTION__);
       return 0;
}

// dev_release will be Called when user close the device file
static int dev_release(struct inode *inode, struct file *filp)
{
       printk("%s():\n",__FUNCTION__);
       return 0;
}

// mainly io control between user and kernel
// args are pointed to user space's buffer
static int val = 0;
static int dev_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long args)
{
      int tmp, err=0,ret=0;

      if(_IOC_TYPE(cmd) != IOC_MAGIC)
              return -ENOTTY;
      if(_IOC_NR(cmd) > IOC_MAXNR)
              return -ENOTTY;
      if(_IOC_DIR(cmd) & _IOC_READ){
              err = !access_ok(VERIFY_WRITE, (void __user*)args, _IOC_SIZE(cmd));
      } else if (_IOC_DIR(cmd) & (_IOC_WRITE)){
              err = !access_ok(VERIFY_READ, (void __user *)args,_IOC_SIZE(cmd));
      }

      if (err)
              return -EFAULT;

      switch (cmd) {
        case SETNUM:
             //copy data from args(user) to val(kernel)
             if(copy_from_user(&val,(int __user *)args,1))
                 return -1;

             printk("%s():get val from user = %d\n",__FUNCTION__,val);
                   break;
        case GETNUM:
                        //copy data from val to args
              if(copy_to_user((int __user *)args,&val,1))
                    return -1;

              printk("%s():set val to %d\n",__FUNCTION__, val);
                    break;
        case XNUM:
                       // exchange data passed by user
              tmp = val;
              if(copy_from_user(&val,(int __user *)args,1))
                        return -1;

              if(copy_to_user((int __user *)args,&val,1))
                        return -1;

           printk("%s():change val from %d to %d\n",__FUNCTION__,tmp,val);
           break;

        default: /* redundant. as cmd was checked against MAXNR */
                 return -ENOTTY;
     }
     return 0;
}


static const char str[]="Hello Irene from kernel!";
static const ssize_t str_size = sizeof(str);
// send messages to user
ssize_t dev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{

     printk("%s():\n",__FUNCTION__);

     if( *f_pos >= str_size)
          return 0;
     if( *f_pos + count > str_size)
        count = str_size - *f_pos;
     if (copy_to_user(buf, str + *f_pos, count))
        return -EFAULT;
     *f_pos += count;
     return count;

}

ssize_t dev_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
     printk("%s():\n",__FUNCTION__);
     return 0;
}

static int __init init_modules(void)

   dev_t dev;
   int ret;
   // get major number dynamically
   ret = alloc_chrdev_region(&dev, 0, 1, "mydev");
   if (ret <0){
      printk("can't alloc chrdev\n");
      return ret;
   }
   dev_major = MAJOR(dev);
   dev_minor = MINOR(dev);
   printk("register chrdev(%d,%d)\n",dev_major,dev_minor);

   dev_cdevp = kmalloc(sizeof(struct cdev), GFP_KERNEL);
   if (dev_cdevp == NULL){
        printk("kmalloc failed\n");
        goto failed;
   }
   // system call handler
   cdev_init(dev_cdevp, &dev_fops);
   dev_cdevp->owner = THIS_MODULE;
   //register my device to kernel
   ret = cdev_add(dev_cdevp, MKDEV(dev_major, dev_minor),1);
   if(ret < 0){
        printk("add chr dev failed\n");
        goto failed;
   }
   return 0;

failed:
   if(dev_cdevp) {
   kfree(dev_cdevp);
   dev_cdevp = NULL;
}
  return 0;
}


static void __exit exit_modules(void)
{
   dev_t dev;
   dev = MKDEV(dev_major, dev_minor);
   if (dev_cdevp){
      cdev_del(dev_cdevp);
      kfree(dev_cdevp);
    }
   unregister_chrdev_region(dev,1);
   printk("unregister chrdev\n");
}

module_init(init_modules);
module_exit(exit_modules);



接著 是 user 端部分啦 test_mydev.c
執行時要輸入的參數有 devicefile num
device file 就是 在 /dev下的裝置檔名
num 是 XNUM命令時要change的value (default 是 10 )
首先利用 open 打開 device file
然後 read(fd, buffer, sizeof(buffer));
buffer 是 user 拿來放kernel 回傳值的地方
此時kernel 會回傳 Hello Irene from kernel!
接著 user 開始下達 ioctl command
--> ioctl(fd, SETNUM, &ret)
這是其中一個例子 , SETNUM 便是user 下達的command
而&ret 是 回傳值的指標

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ioc.h"

int main(int argc, char *argv[])
{
       int fd, ret=10;
       unsigned char buffer[50]={};
       if(argc < 2)
       { 
         printf("Usage: /dev/mydev param1.. \n"); 
         return -1;
       }
       // open dev file
       fd=open(argv[1], O_RDWR);
       if(fd < 0)
       {
           printf("open %s failed\n", argv[1]);
           return -1;
       }
       //read from kernel  
       read(fd, buffer, sizeof(buffer));
       printf("%s\n",buffer);
       // set num to 10
       if (ioctl(fd, SETNUM, &ret)< 0)
       {
           printf("set num failed\n");
           return -1;
       }
       if(ioctl(fd, GETNUM , &ret)< 0)
       {
           printf("get num failed\n");
       }
       printf("get default value=%d\n",ret);
       // exchange number ret =atoi(argv[2]);  
       if (ioctl(fd, XNUM, &ret)<0)
       {
           printf("exchange num failed\n");
           return -1;
        }
       printf("get value = %d\n",ret);
       return 0;
} 


最後是 Makefile








上面全部的檔案都存在mydev 資料夾中
/usr/src/kernels/linux-2.6.18/mydev/..

開始執行
make 之後的指令如下
 











在 insmod之後 dev會被賦予 major number 與 minor number 
開啟新的cmd 執行dmesg就可以看到kernel傳來一條msg
register  chrdev(252,0)
或是可以到 /proc/devices中查看 major number 與 minor number
在mknod時一定要給定對的major 與 minor number
否則會有 找不到 file 的錯誤
執行後可以看到
kernel 傳回一條 hello messages
而kernel也將預設為10 的value改為 user 設定的 100
最後dmesg中可以看到kernel的訊息

 










研究好多天仍有很多疑問, 有不完備之處之後繼續修改
參考:
 http://csw17.pixnet.net/blog/post/11506143
http://nano-chicken.blogspot.tw/2009/12/linux-modulesv-ioctl.html
http://www.codeproject.com/Articles/112474/A-Simple-Driver-for-Linux-OS
強烈建議大家在寫這個之前先到jollen的網站看相關的 device 觀念教學

 

 

 

 

 

文章來源

http://blackcat12573.blogspot.tw/2013/09/linux-device-driver-ioctl-copytouser.html

mybeauty 發表在 痞客邦 留言(1) 人氣()

來源:

Linux 驅動程式的 I/O, #3: kernel-space 與 user-space 的「I/O」

Linux 驅動程式的 I/O, #4: fops->ioctl 實作

 

重要觀念

任何作業系統底下的「驅動程式」,都需要分二個層面來討論所謂的「I/O 處理」:

1. 實體層:驅動程式 v.s. 硬體。

2. 虛擬層:驅動程式 v.s. user process

在前一篇日記「Linux 驅動程式的 I/O, #2: I/O 存取相關函數」中所提到的 I/O 函數是處理「實體層」的 I/O;本日記所要介紹的 copy_to_user()  copy_from_user() 則是在處理「虛擬層」的 I/O。另外,在繼續往下讀之前,您必須了解以下的觀念都是「等價」的:

1. 驅動程式與 user process 的 I/O;等於

2. 驅動程式與 user process 間的 data communication;等於

3. kernel-space 與 user-space 間的 data communication。

此外,還要了解:

1. user-space 無法「直接」存取 kernel-space 的記憶體。

2. 「Linux device driver」與「user-space」間的 I/O 會與 fops->readfops->write  fops->ioctl 共三個 system call 有關。

copy_to_user() 與 copy_from_user()

了解以上的觀念後,再來「直接殺進重點」就很容易懂了:從 user-space 讀取資料至 kernel-space,或是將 kernel-space 的資料寫至 user-space,「必須」透過 kernel 提供的 2 個 API 來進行。這二個 API 如下:

˙ long copy_to_user(void *to, const void *from, long n);
˙ long copy_from_user(void *to, const void *from, long n);

參數說明,以 copy_to_user() 來說:

˙ to:資料的目的位址,此參數為一個指向 user-space 記憶體的指標。
˙ from:資料的來源位址,此參數為一個指向 kernel-space 記憶體的指標。
˙ 口訣:copy data to user-space from kernel-space

 copy_from_user() 來說:

˙ to:資料的目的位址,此參數為一個指向 kernel-space 記憶體的指標。
˙ from:資料的來源位址,此參數為一個指向 user-space 記憶體的指標。
˙ 口訣:copy data from user-space to kernel-space

由 user-space 讀取資料,或是寫入資料給 user-space 的 3 個 driver method 為:read、write與ioctl。

另外,指向 user-space 的指標是 kernel 回呼 driver method 時所傳遞進來的,可由 read、write 與 ioctl driver function 的函數原型宣告來觀察(紅色部份):

˙ int card_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
˙ ssize_t write(struct file *filp, const char *buff, size_t count, loff_t *offp);
˙ ssize_t read(struct file *filp, char *buff, size_t count, loff_t *offp);

fops->ioctl 的參數 arg、fops->write 與 fops->read 的參數 buff 是指向 user-space 資料的指標。撰寫程式時,要注意資料型別上的不同。

 

 

基本觀念

需要由 user-space 讀取資料,或是寫入資料給 user-space 的主要 3 個 driver method 為:read、write 與 ioctl。指向 user-space 資料空間(buffer)的指標是 kernel 回呼 driver method 時所傳遞進來的,我們由 read、write 與 ioctl 的函數原型宣告來說明如何撰寫程式:

˙int card_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
˙ssize_t write(struct file *filp, const char *buff, size_t count, loff_t *offp);
˙ssize_t read(struct file *filp, char *buff, size_t count, loff_t *offp);

fops->ioctl 的參數 argfops->write  fops->read 的參數 buff 是指向 user-space 資料的指標。撰寫程式時,要注意資料型別上的不同。

實作 fops->ioctl

ioctl 代表 input/output control 的意思,故名思義,ioctl system call 是用來控制 I/O 讀寫用的,並且是支援user application存取裝置的重要 system call。因此,在 Linux 驅動程式設計上,我們會實作 ioctl system call 以提供 user application 讀寫(input/output)裝置的功能。

依此觀念,當 user application 需要將數字顯示到 debug card 時。範例 debug card 0.1.0 便需要實作 ioctl system call,然後在 fops->ioctl 裡呼叫 outb() 將 user application 所指定的數字輸出至 I/O port 80H。

User application 使用 GNU LIBC 的 ioctl() 函數呼叫 device driver 所提供的命令來「控制」裝置,因此驅動程式必須實作 fops->ioctl以提供「命令」給使用者。

fops->ioctl 函數原型如下:

int ioctl(struct inode *, struct file *, unsigned int, unsigned long);

Linux 驅動程式以一個唯一且不重覆的數字來代表 ioctl 的命令,設計 Linux 驅動程式時,我們必須使用 kernel 所提供的巨集來宣告命令。根據命令的「方向」,kernel 提供以下 4 個巨集供我們宣告 ioctl 命令:,

  • _IO(type,nr):表示此 ioctl 命令不指定資料向方
  • _IOR(type,nr,dataitem):此 ioctl 命令由裝置 (driver) 讀取資料
  • _IOW(type,nr,dataitem):此 ioctl 命令將資料寫入裝置
  • _IOWR(type,nr,dataitem):此 ioctl 命令同時讀寫資料

若 user application 呼叫到驅動程式未提供的命令,則回傳 -ENOTTY 錯誤代碼。

debug card 0.1.0 範例裡,我們宣告了一個 IOCTL_WRITE 命令,當 user application 呼叫此命令後,驅動程式會將 user application 所指定的數字顯示在 debug card 上。由於我們的資料方向為「寫入裝置」,因此使用的宣告巨集為 _IOW

Debug card 0.1.0 實作 fops->ioctl 的完整程式片斷如下:

#include <linux/ioctl.h>

#define	DEV_MAJOR	121
#define	DEV_NAME	"debug"
#define  	DEV_IOCTLID	0xD0
#define	IOCTL_WRITE	_IOW(DEV_IOCTLID, 10, int)

unsigned long IOPort = 0x80;

void write_card(unsigned int);

void write_card(unsigned int num)
{
	outb((unsigned char)num, IOPort);
}

int card_ioctl(struct inode *inode, struct file *filp,
	  unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
		case IOCTL_WRITE:
			write_card((unsigned int)arg);
			break;
		default:
			return -1;
	}
    	return 0;
}

struct file_operation 的定義並未列出,不過請別忘了在 fops 裡加上 ioctl system call 的欄位。

User-space

以 debug card 0.1.0 驅動程式為例,user-space 的測試程式寫法如下:

int main(int argc, char *argv[])
{
    int devfd;
    int num = 0;

    if (argc > 1) num = atoi(argv[1]);
    if (num < 0) num = 0xff;

    devfd = open("/dev/debug", O_RDONLY);
    if (devfd == -1) {
	printf("Can't open /dev/debug\n");
	return -1;
    }

    printf("Write 0x%02x...\n", num);
    ioctl(devfd, IOCTL_WRITE, num);
    printf("Done. Wait 5 seconds...\n");
    sleep(5);
    close(devfd);

    return 0;
}

 

來源

http://huenlil.pixnet.net/blog/post/23507650

mybeauty 發表在 痞客邦 留言(0) 人氣()

動手寫 Linux Driver

 
先前為了一個期末專題花了一點時間研究怎麼在 Linux 作業系統上寫一個 PCI Driver。寫過 Linux 驅動程式之後,覺得 Linux 的架構真的很漂亮!為了怕以後忘記怎麼寫,所以就把他寫下來記錄成一篇文章。
 

建構編譯環境


先我們必須要準備開發 Linux 驅動程式所需的環境,在 Debian 上可以用以下的指令達到這個目的:

$ sudo apt-get install build-essential linux-headers-$(uname -r)

其中 build-essential 會安裝 gcc, make 等軟體開發必要的工具,而 linux-headers 會安裝開發 Linux 驅動程式必要的 SDK。因為 linux-headers 會隨核心的版本而有所不同,所以我們要使用 $(uname -r) 取得目前核心的版本。
 

簡單的驅動程式


所有的 Linux 驅動程式至少要包含一個 MODULE_LICENSE 用以宣告驅動程式的授權,另外還需要一個 init 與一個 exit 函式,分別處理驅動程式的起始與終止。以下就是一個什麼都沒有的空殼:

/* example.c */
#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");

static int example_init(void) {
    printk("<1>EXAMPLE: init\n");
    return 0;
}

static void example_exit(void) {
    printk("<1>EXAMPLE: exit\n");
}

module_init(example_init);
module_exit(example_exit);

我們可以注意到裡面有一個 printk,他就相當於驅動程式設計當中的 printf。我們如果需要印任何除錯資訊,可以呼叫 printk,然後使用 sudo dmesg 觀看結果。編譯這個檔案之前,我們要先幫他寫 Makefile:

obj-m := example.o

ifeq ($(KERNELDIR),)
KERNELDIR=/lib/modules/$(shell uname -r)/build
endif

all:
    make -C $(KERNELDIR) M=$(PWD) modules

clean:
    make -C $(KERNELDIR) M=$(PWD) clean

在這個 Makefile 裡面,我們會使用 obj-m 這個變數指定我們要編譯的模組,然後再呼叫 make 讓他載入 SDK 的 Makefile。我們先前安裝的 SDK 就會放在 /lib/modules/$(shell uname -r)/build 裡面。

接下來我們就可以用 make 編譯我們的模組,並使用以下指令載入、卸除模組:

$ sudo insmod ./example.ko
$ sudo rmmod example

如果要看我們的模組有沒有輸出任何訊息,可以使用:

$ sudo dmesg | tail
 

註冊為 Character Device


在 Unix 的設計哲學當中,所有的東西都是檔案,硬體也不例外。我們寫驅動程式的時候要提供一個檔案操作的介面給 Userspace 的程式。為了達到這個目的,我們必須再引入一個標頭檔:

#include <linux/fs.h>

然後定義若干檔案操作與 file_operations 這個資料結構:

static int example_open(struct inode *inode, struct file *filp) {
    printk("<1>EXAMPLE: open\n");
    return 0;
}

static int example_close(struct inode *inode, struct file *filp) {
    printk("<1>EXAMPLE: close\n");
    return 0;
}

static ssize_t example_read(struct file *filp, char *buf, size_t size, loff_t *f_pos) {
    printk("<1>EXAMPLE: read  (size=%zu)\n", size);
    return 0;
}

static ssize_t example_write(struct file *filp, const char *buf, size_t size, loff_t *f_pos) {
    printk("<1>EXAMPLE: write  (size=%zu)\n", size);
    return size;
}

static struct file_operations example_fops = {
    .open = example_open,
    .release = example_close,
    .read = example_read,
    .write = example_write,
};

然後在 example_init() 當中用 register_chrdev 把這個驅動程式註冊為一個 Character Device。

#define EXAMPLE_MAJOR 60
#define EXAMPLE_NAME "example"

static int example_init(void) {
    int result;
    printk("<1>EXAMPLE: init\n");

    /* Register character device */
    result = register_chrdev(EXAMPLE_MAJOR, EXAMPLE_NAME, &example_fops);
    if (result < 0) {
        printk("<1>EXAMPLE: Failed to register character device\n");
        return result;
    }

    return 0;
}

值得一提的是第一個參數 EXAMPLE_MAJOR 可以是 60, 61, 62。如果是正式要釋出的 Driver,就必須要從 Documentation/devices.txt 選取適當的 Major ID。當然,在 example_exit() 我們也必需加上對應的 unregister:

static void example_exit(void) {
    printk("<1>EXAMPLE: exit\n");

    /* Unregister character device */
    unregister_chrdev(EXAMPLE_MAJOR, EXAMPLE_NAME);
}

在重新編譯之後,我們可以用 insmod 載入驅動程式,然後使用 mknod 建立 Device File。然後我們就可以在 User Space 使用一般的檔案讀寫操作這個 Device。

$ sudo insmod ./example.ko

$ sudo mknod /dev/example c 60 0
# /dev/example 是我們要存放檔案的路徑,c 代表 Character Device,60 是這個驅動程式的 Major ID,0 是驅動程式的 Minor ID。

$ sudo chmod 666 /dev/example
# 為了方便測試,我們把這個 Device 改成所有人都可以讀寫。

$ echo -n 'abcd' > /dev/example

$ sudo dmesg | tail
 

讀取 User Space 的資料


在前一節當中我們提供了一個 API 讓 User Space 可以操作 Driver。但是其實我們是不能直接存取 buf 的內容。因為 Kernel Space 與 User Space 有不同的位址空間,所以不能直接存取他們。我們必須借助 copy_from_user 這個 API。

在使用這個 API 之前,我們必需引入 <asm/uaccess.h>:

#include <asm/uaccess.h>

然後我們就可以使用 copy_from_user 來存取 User Space 的位址空間,舉例來說:

ssize_t example_write(struct file *filp, const char *buf, size_t size, loff_t *f_pos) {
    size_t pos;
    uint8_t byte;
    printk("<1>EXAMPLE: write  (size=%zu)\n", size);
    for (pos = 0; pos < size; ++pos) {
        if (copy_from_user(&byte, buf + pos, 1) != 0) {
            break;
        }
        printk("<1>EXAMPLE: write  (buf[%zu] = %02x)\n", pos, (unsigned)byte);
    }
    return pos;
}

值得注意的是 copy_from_user() 會回傳剩下未完成的 byte 數。所以一般來說這個回傳值必須是 0 才是成功地讀入資料。要把資料從 Kernel Space 複製到 User Space 則是使用 copy_to_user() 函式,至於使用方法就不再贅述。

$ echo -n 'abcd' > /dev/example
$ sudo dmesg | tail 
 

小結


透過這個小練習,我們可以知道要怎麼開始寫一個 Linux Driver。在下一結我們會從 QEMU 的角度出發,建立一個 QEMU 的虛擬裝置,讓 QEMU Guest OS 的驅動程式可以和外面的 QEMU 虛擬裝置相互溝通。
 

參考資料

 

 

來源

http://blog.logan.tw/2013/01/linux-driver.html

 

 

mybeauty 發表在 痞客邦 留言(0) 人氣()

 

LibCurl supports URL transfer over HTTPS protocol. In this post we’ll use LibCurl to download a webpage over HTTPSprotocol. To get started, make sure that you have setup your system as outlined in one of my previous posts. Note that LibCurl comes with SSL libraries included and hence you need not to install any extra packages.

Getting started

Let’s first try to download a HTTPS webpage without SSL using following code:

 1 #include <stdio.h>
 2 #define CURL_STATICLIB
 3 #include <curl/curl.h>
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     CURL *curl;
 8     CURLcode res;
 9 
10     curl = curl_easy_init();
11     if (curl)
12     {
13         curl_easy_setopt(curl, CURLOPT_URL, "https://google.com");
14         /* google.com is redirected, so we tell LibCurl to follow redirection */
15         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
16 
17         /* Perform the request, res will get the return code */
18         res = curl_easy_perform(curl);
19         /* Check for errors */
20         if(res != CURLE_OK)
21             fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
22 
23         /* Always cleanup */
24         curl_easy_cleanup(curl);
25     }
26 
27     return 0;
28 }

When we compile and run the above program, we get following error:

curl_easy_perform() failed: Peer certificate cannot be authenticated with given CA certificates

Well we can force LibCurl not to verify the authencity of peer’s certificate by modifying the program as below:

 1 #include <stdio.h>
 2 #define CURL_STATICLIB
 3 #include <curl/curl.h>
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     CURL *curl;
 8     CURLcode res;
 9 
10     curl = curl_easy_init();
11     if (curl)
12     {
13         curl_easy_setopt(curl, CURLOPT_URL, "https://google.com");
14         /* google.com is redirected, so we tell LibCurl to follow redirection */
15         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
16         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
17         /* Perform the request, res will get the return code */
18         res = curl_easy_perform(curl);
19         /* Check for errors */
20         if(res != CURLE_OK)
21             fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
22 
23         /* Always cleanup */
24         curl_easy_cleanup(curl);
25     }
26 
27     return 0;
28 }

This will resolve the error we were getting earlier but this is not secure as we are bypassing the verification of SSLcertificte presented by peer.

LibCurl with SSL

Now let’s modify the code as below to enable SSL certificate verification by LibCurl:

 1 #include <stdio.h>
 2 #define CURL_STATICLIB
 3 #include <curl/curl.h>
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     CURL *curl;
 8     CURLcode res;
 9 
10     curl = curl_easy_init();
11     if (curl)
12     {
13         curl_easy_setopt(curl, CURLOPT_URL, "https://google.com");
14         /* google.com is redirected, so we tell LibCurl to follow redirection */
15         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
16         /* SSL Options */
17         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , 1);
18         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , 1);
19         /* Provide CA Certs from http://curl.haxx.se/docs/caextract.html */
20         curl_easy_setopt(curl, CURLOPT_CAINFO, "ca-bundle.crt");
21 
22         /* Perform the request, res will get the return code */
23         res = curl_easy_perform(curl);
24         /* Check for errors */
25         if(res != CURLE_OK)
26             fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
27 
28         /* Always cleanup */
29         curl_easy_cleanup(curl);
30     }
31 
32     return 0;
33 }

LibCurl depends on ca-bundle.crt to verify server’s certificate. CA bundle extract is provided by LibCurl itself and you can download it from here. We need to place the ca-bundle.crt in same folder as our executable. Also notice that we have enabled CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST in lines 17 and 18. When CURLOPT_SSL_VERIFYPEER is enabled, LibCurl verifes if the ceriticate presented is authentiate or not. If the verification fails to prove that the certificate is authentic, the connection fails. Authenticating the certificate is not enough to be sure about the server. We also want to ensure that the server is the server we mean to be talking to. When CURLOPT_SSL_VERIFYHOST is enabled, LibCurl checks that the host name in the certificate is valid for the host name we’re connecting to. If LibCurl fails to verify this, the connection fails.

 

 

 

 

 

來源

https://pranavprakash.net/2014/09/27/using-libcurl-with-ssl/

mybeauty 發表在 痞客邦 留言(0) 人氣()

最近在做使用openssl链接http和https的项目,编译时出现以下问题。

/usr/local/openssl/lib/libcrypto.a(async.o): In function `async_free_pool_internal':
async.c:(.text+0xe4): undefined reference to `pthread_setspecific'
async.c:(.text+0xf4): undefined reference to `pthread_getspecific'
async.c:(.text+0x104): undefined reference to `pthread_setspecific'
/usr/local/openssl/lib/libcrypto.a(async.o): In function `ASYNC_init_thread.part.1':
async.c:(.text+0x253): undefined reference to `pthread_setspecific'
/usr/local/openssl/lib/libcrypto.a(async.o): In function `async_start_func':
async.c:(.text+0x36f): undefined reference to `pthread_getspecific'
async.c:(.text+0x39e): undefined reference to `pthread_getspecific'
/usr/local/openssl/lib/libcrypto.a(async.o): In function `ASYNC_start_job':
async.c:(.text+0x404): undefined reference to `pthread_getspecific'
async.c:(.text+0x41e): undefined reference to `pthread_getspecific'
async.c:(.text+0x433): undefined reference to `pthread_getspecific'
/usr/local/openssl/lib/libcrypto.a(async.o):async.c:(.text+0x44c): more undefined references to `pthread_getspecific' follow
/usr/local/openssl/lib/libcrypto.a(async.o): In function `ASYNC_start_job':
async.c:(.text+0x7ef): undefined reference to `pthread_setspecific'
async.c:(.text+0x811): undefined reference to `pthread_getspecific'
async.c:(.text+0x82d): undefined reference to `pthread_getspecific'
async.c:(.text+0x83f): undefined reference to `pthread_getspecific'
async.c:(.text+0x870): undefined reference to `pthread_getspecific'
async.c:(.text+0x891): undefined reference to `pthread_getspecific'
/usr/local/openssl/lib/libcrypto.a(async.o):async.c:(.text+0x8a6): more undefined references to `pthread_getspecific' follow
/usr/local/openssl/lib/libcrypto.a(async_posix.o): In function `async_global_init':
async_posix.c:(.text+0xc): undefined reference to `pthread_key_create'
async_posix.c:(.text+0x1e): undefined reference to `pthread_key_create'
/usr/local/openssl/lib/libcrypto.a(async_posix.o): In function `async_local_init':
async_posix.c:(.text+0x3d): undefined reference to `pthread_setspecific'
async_posix.c:(.text+0x50): undefined reference to `pthread_setspecific'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_globallookup':
dso_dlfcn.c:(.text+0x21): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x34): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x3f): undefined reference to `dlclose'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_bind_func':
dso_dlfcn.c:(.text+0x354): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x3fb): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_bind_var':
dso_dlfcn.c:(.text+0x474): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x52e): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_load':
dso_dlfcn.c:(.text+0x5a4): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x60b): undefined reference to `dlclose'
dso_dlfcn.c:(.text+0x638): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_pathbyaddr':
dso_dlfcn.c:(.text+0x6ce): undefined reference to `dladdr'
dso_dlfcn.c:(.text+0x731): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_unload':
dso_dlfcn.c:(.text+0x78a): undefined reference to `dlclose'

 

解决方案:

=======================================================================================================

gcc obj/Debug/main.o -L/usr/local/openssl/lib -lssl -lcrypto -ldl -lpthread -o main

原因分析:

在链接这个库的时候一定要注意2个问题:

1.openssl库的版本问题,请直接链到你需要的openssl库路径,比如我的就是/usr/local/openssl/lib,

2.注意-lssl -lcrypto要写在-ldl -lpthread前面,这四个必须要。

相关知识:

-L :此选项是指定链接库的文件夹地址

-l(小写的L):-lssl 即是寻找/usr/local/openssl/lib目录下的 libssl.a 这个库,编译器会自动寻找 libssl.a或者libssl.so

-I(大写的i):指定头文件的文件夹地址

 
來源
http://www.cnblogs.com/Boyona/p/4999339.html

mybeauty 發表在 痞客邦 留言(0) 人氣()

整理virtualBox的上網設定

-------------------------------------------------------------------

 

寫在前面

(1) 這一篇文章是說明VirtualBox內的Ubuntu,設定2張網卡,一張NAT可以透過Host的win 7筆電上大網。

另一張Bridge連到embedded開發板。這是不上大網的,是設定成固定IP

(2) 要注意的事Bridge在VirtualBox裡設定完成之後,要進Ubuntu設定Bridge這張網卡的IP

 

-------------------------------------------------------------------

這一篇是我看過最詳細的說明

VirtualBox能設定4張網卡,連線模式在下面這篇文章寫的很清楚。

http://kanchengzxdfgcv.blogspot.tw/2015/10/oracle-vm-virtualbox.html

 

以下使得Ubuntu可以出大網,也可以和arm的板子對接。

-------------------------------------------------------------------
注意!
/etc/network/interfaces的設定要這樣子寫
NAT那一張不用寫上來
bridge那一張不要設gateway

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto enp0s3
iface enp0s3 inet static
address 192.168.0.105
netmask 255.255.255.0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

mybeauty 發表在 痞客邦 留言(0) 人氣()

來源

http://wdpsestea.blogspot.tw/2016/02/inkscape091.html

 

 

inkscape0.91當機問題解決方法

 
這個問題困援許久,本以為我們解決不了,想不到師父就是師父,子忠老師查出哪裡出問題,並把它修復並且釋出檔案。
原來是中文化檔案出問題,並釋出檔案了。請下載此檔案
https://drive.google.com/file/d/0B8MclADHBn8eNlYtZ3BkdEZKT1U/view?usp=sharing

把它放入/usr/share/locale/zh_TW/LC_MESSAGES資料夾中。inkscape0.91版當掉問題就解決了。

 

 

mybeauty 發表在 痞客邦 留言(0) 人氣()

QT的正規表示法應用看官網說明就有了。

http://doc.qt.io/qt-5/qregularexpression.html

 

轉貼下面的文章,這篇文章非常的清楚好懂。

http://blog.kkbruce.net/2012/02/javascript-regular-expression.html#.Vw8SG_l97IU

 

JAVASCRIPT - 表單元素 - REGULAR EXPRESSION

 

REGULAR EXPRESSION

 
Regular Expression(正規表達式) - 基本字元
名稱 說明
\n 換行符號
\r Enter
\t Tab
\xHex 16進位ASCII
\xOct 8進位ASCII
\符號 轉義,讓符號只是符號,無RE作用

因為符號在RE裡有其他作用,\.代表.、\?代表?,符號有:.、?、/、\、[、]{、}、(、)、+、*、|。
 
Regular Expression(正規表達式) - 字元集"["與"]"符號"
名稱 說明
[abc] 代表英文a、b、c
[a-z] 代表26個英文小寫
[A-Z] 代表26個英文大寫
[0-9] 代表數字0到9
[a-zA-Z] 代表所有大小寫英文
[^abc] 除了a、b、c以外任何字元
- 英文或數字的一個範圍
[^] 在[]裡的^為排除的意思

[ ]代表一個區段、段落。
 
Regular Expression(正規表達式) - 常用範圍
名稱 說明
\w [0-9a-zA-Z_],任何英數字和底線
\W [^0-9a-zA-Z_],也就是^\w的意思
\d [0-9],任何數字
\D [^0-9],也就是^\w的意思
\s 比對空格,空白字元(space)、tab、換行字元、return/enter
. .(點)比較任何字元,換行字元(newline)除外

以上都是常用的Escape字串。
 

Regular Expression語法

 
1 var reName = /pattern/[g|i|gi];

使用變數來儲存pattern,遇/.../字串自動建立RegExp物件。把pattern被在"//"符號之間,就是你所要過濾的規則,例如/[0-9]/。
 

[g|i|gi]選擇性參數,尋找方式

  • g:比對字串中所有符合pattern字串的子字串, 如果沒有設定,將只找第一個符合pattern的字串
  • i:不區分pattern字串的英文大小寫
 
尋找方式範例
 
1 // jscript(j小寫)和Jscript(J大寫)都符合
2 var reJS1 = /[jJ]script/;
3 // 2*2會出現四種符合的組合
4 // javascript、javaScript、Javascript、JavaScript
5 var reJS2 = /[jJ]ava[sS]cript/;

^開頭$結尾

 
1 // 找出開頭是This的字串
2 // 注意,此^不是放在[^],位置不同作用不同
3 var reStar = /^This/;
4 // 找出結尾是bye.的字串
5 var reEnd = /bye.$/
 
Regular Expression(正規表達式) - ^開頭$結尾
名稱 說明
^ 比對字串開頭
$ 比較字串結尾
 

^開頭$結尾範例

 
1 // 需要指定「出現次數」,例如身分證
2 // A123456789,第一碼為英文,第二碼為男女,3-9碼為數字
3 var reID = /^[a-zA-Z]{1}[1-2]{1}[0-9]{8}/;
 

量詞

 
Regular Expression(正規表達式) - 量詞
名稱 說明(次數)
? 0或1次
* 0或多次
+ 1或多次
{n} 出現n次
{n,} 至少n次
{n,m} n到m次
( ) 集合字元或/和中介字元,成為子樣式

最後一個(),我們舉個例子,「/(Hot)? ?Donuts/」過濾條件,可比對出Donuts或Hot Donuts。而「/(red|blue) pill/] 過濾條件,可比對出red pill或blue pill。

定義好樣式(pattern)後,可使用test()方法來測試。
 
1 // 定義過濾條件
2 var regex = /^\d{5}/$;
3 // 使用test()測試是否符適合條件
4 if (!regex.test(inputField.Value))
5   ...
 

RegExp物件

 
1 var objRE = new RegExp("pattern字串", "g|i|gi");

第一個pattern字串(不需放在//符號之間),第二個為尋找方式的參數。使用RegExp物件的test()方法進行比對,符合回傳true。
 
1 objRE.test(strValue);

如果在JavaScript字串變數需要尋找是否擁有符合Regular Expression的pattern子字串,此時請使用String物件的match()方法,例如,
 
1 String.match(objRE);

字串(String)的match()方法範例,
 
1 var str = "This is book.";
2 var objRE = new RegExp("is", "g");
3 var result = str.match(objRE);

我們將比對結果儲存起來,然後,
 
1 // 沒有會傳回null,有會傳回Array
2 // is, is --> 陣列
3 document.write(result);
4 // 傳回符合數量
5 // 2
6 document.write(result.length);

mybeauty 發表在 痞客邦 留言(0) 人氣()

The point is: Please download the package qt-opensource-windows-x86-android-5.6.0.exe

It is in http://download.qt.io/official_releases/qt/5.6/5.6.0/

You also can download in http://www.qt.io/download-open-source/#section-2

 

Other material you can google "Qt for Android" on internet.

Please read official QT document first.

----

我之前花了很多時間就是弄不出來,後來我終於發現了...原來很容易..

重點只有一個,但是網路上沒有寫。所以我弄了又弄,弄了又弄...

 

安裝檔請到這裡下載 http://download.qt.io/official_releases/qt/5.6/5.6.0/

要抓這一個檔案  qt-opensource-windows-x86-android-5.6.0.exe

一定要for Android的才有這些設定。之前白費了好多時間。囧。

 

也可以如上圖由此下載

http://www.qt.io/download-open-source/#section-2

 

 

我的靈感是從這裡來的

http://download.qt.io/official_releases/qt/5.6/5.6.0/

 

 

mybeauty 發表在 痞客邦 留言(0) 人氣()

QT 5.5, windows 7, and MySQL
 
 
I have done QT 5.5 and MySQL connection.
Running official QT example SQL Browser works fine.
I share my experience here. 
 
 
(1) MySQL's sql driver can be found under QT directory
Path:
C:\Qt\Qt5.5.1\5.5\mingw492_32\plugins\sqldrivers
File names are: qsqlmysql.dll及 qsqlmysqld.dll
(We do not need to compile SQL driver) 
 
(2) We need to add SQL library support in *.pro file as below.
QT += sql

 

 
(3) The point is under Windows 7 (Win7), we need to put libmysql.dll to the folder of *.exe file. Here is my example. The *.exe file is sqlbrowser.exe.
2016-03-14 09_00_41-debug.png
 
How can we get libmysql.dll?
Please go to MySQL website, and download "Windows (x86, 32-bit), ZIP Archive".
Unzip the zip file and you can get it in mysql-5.7.11-win32\lib\libmysql.dll
Copy libmysql.dll file to the same folder with *.exe.
 
 
Let me summary my article. You just need to do the step (3). (The part in blue)
 
Reference:
https://forum.qt.io/topic/36371/solved-qt5-2-can-find-the-mysql-driver-but-can-not-load-it/4
 
 
 

mybeauty 發表在 痞客邦 留言(0) 人氣()

QT 5.5, windows 7, and MySQL
 
我把QT5.5 和MySQL弄好了。
可以run官方example SQL browser,並連上我建的MySQL資料庫。
把說明整理如下
 
(1) Mysql的sql driver在QT下就有。
路徑
C:\Qt\Qt5.5.1\5.5\mingw492_32\plugins\sqldrivers
檔名qsqlmysql.dll及 qsqlmysqld.dll
 
(網路上的文章說要編SQL driver。SQL driver的source code是在QT source code裡,我下載的mingw版QT沒source code。但是driver已經編好了,總之不需要再去編SQL driver)
 
(2) *.pro檔要加入sql的支援,語法如下
QT += sql

 

(3) 重點是在Windows 7下,要把libmysql.dll複製到和執行檔一起放。
例如下面是我的sample。
另一個重點是libmysql.dll是從哪裡來的呢?要從MySQL官網裡找
下載Windows (x86, 32-bit), ZIP Archive
然後解開後,在mysql-5.7.11-win32\lib\libmysql.dll
複製到和*.exe在同一層,就可以用。
 
怕各位看不懂我的文章,我總結一下,只要做上面的步驟(3)就可以了。
 
 
 

mybeauty 發表在 痞客邦 留言(0) 人氣()

1 23