我測試了可以用 ^^
我測試了可以用 ^^
新電腦的source insight在外接螢幕上很模糊,但是用Chrome又很正常。
試一下很久,下面的解法有效。
要單獨為source insight做設定。
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:
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
我有個軟體視窗,每次打開後就飄到另一個螢幕。
但是我並沒有接那個螢幕啊 orz
上網找到解法了。轉貼如下
中文
Windows 10 執行程式之後,卻看不到視窗,但是,底下的工作bar卻有出現,Alt+TAB也可以看到應用程式在執行…
只好請出 Google 大神,找到 Microsoft 網站上的解答:
結果真是令人失望,還好這篇有解法:
http://ilyvonne.pixnet.net/blog/post/26863403-視窗跑到螢幕外-該怎麼辦?
整理一下步驟:
1.從底下的工作bar,點選到應用程式
2.【Alt+space】
3.【移動(M)】
4.使用上下左右的方向鍵,或是 mouse,將視窗【拖】回正常的位置
謎之音…好爛的 bug !
英文
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.)
面試官心得-1 (軟體工程師)
我一直想要把我的面試心得分享給網友,我貼在我的部落格裡面,也許能看到的人不多。
不過我想貼在這裡的自由度比較高,網友若有任何問題也可以問我,
不過我是一個很忙的人,可能也不太有時間回覆大家。
我當面試官大概有5年多的經驗,每年應該會面試到20個人左右。第一篇先寫個總論吧。
***剛出社會的新鮮人
首先,鼓勵大家在學校要好好學習。對我們出社會很久的人來說,剛從學校畢業的新鮮人,所學會的東西真的非常的少。但是如果你在研究所學的很特別,對我們業界有即戰力,是很大的加分。
如果你真的什麼都不會,那也沒有關係,有些好心的主管,會當你是一張白紙開始訓練,但是我覺得這個機會不是很多。一般來說,小公司比較有可能,因為小公司並不好找人,但是大公司可以挑選的人很多。
ptt上很多人,第一份工作決定了你後來的工作,我也是這麼認為。例如你一開始就做測試, 當你要換第二份工作,我相信有很多測試的工作會找你。在電子業界來說,不只是隔行如隔山,即使軟體業界,所需要的知識差異也非常大。
第一份工作,我覺得是以磨練工作技能為主,能不能進大公司要看運氣,如果又是大公司又是自己的興趣最好,可遇而不可求。
***年輕工程師
前一份工作的經驗,大概就會決定你下一份工作要做什麼。通常面試主管,會找有相關經驗的人。有時候扯的上一點點邊,就可以了,所以多學多看是很重要的,哪怕就這麼一點點經驗,剛好是下一份工作所需要的。例如,我要找一個會寫APP的工程師,雖然他只曾經寫過很簡單的一個App,但是我覺得他對物件導向APP開發有基礎的認識。我可以進來再訓練他。
***資深的工程師
我這裡定義的資深,大概是年紀在40歲以上。40歲以上的工程師會不會很難找工作呢?我相信很多人都有這個疑問,以我的觀點,40歲到45歲的工程師,如果技術很好,找新工作並不難。我也曾經錄用過50歲的工程師,不過他是同事介紹的。
二三十年前,很多人都說,希望在科技界撈一筆,然後就退休或是做其他的工作。我今日來看, 並不容易達成,我的同學們也都在上班,目前還沒看到誰真正去退休了。
很多人說寫code能不能寫到一輩子,我覺得至少寫到50歲沒有問題。其實學得越多,學習會越快。有一個重點是,我覺得對工作要有興趣,因為做研發工作普遍來說工時很長,如果沒有興趣,只會自己覺得被困在牢籠裡,長期來說並不是很好。
如果我要任用40歲以上的工程師,只有兩種選擇,第一個是他的技術很好,第二個是他能夠當主管能帶人。 我認為並不是每一個人,都要去追求當主管。軟體工程師的價值還是在技術,即使是軟體主管,仍然要有一定的技術底子。我曾經面試過兩位軟體主管,我感覺應徵者沒有霸氣,沒有那種會讓人想追隨的感覺,可能他只是因為待的久,所以當上了主管。
***坊間的軟體培訓課程有用嗎
我覺得多少有加分,但是這仍然只是學習的程度。最好的狀況是曾經在前份工作有做過類似的專案,學習與商業應用仍有很大的不同,商業應用上要處理很多問題。比方說是防呆, 比方說硬體速度太慢,或者是,在公司的環境下,實作的速度會比較快,除了軟體功力之外,也會訓練抗壓性,和解題的速度。
我個人是以在前份工作做過類似的專案為優先。學校環境, 也有過於理想化的情況。我們在業界,需要的是可維護性,可執行性,還有就是速度要很快。有時候並不一定做得很完美,完美可能也不存在於真正的軟體產品當中。我們看到市面上的軟體很完美,那是因為已經經歷過好幾代的開發以及維護,第一版的軟體只要架構有設計好,經過一定的測試就可以了。要達到極穩定需要一段時間。完成之後,也需要一段時間,讓客戶修改少部分的行為。
***解不出來怎麼辦
曾經有幾位面試者,問我如果bug解不出來怎麼辦。當然這就是我們做leader要去克服的問題。一般來說,應該沒有解不出來的bug,只要有原始碼,都能夠一行一行的去找。但是真實的情況,是時間非常的不夠,每一個公司給RD的時間都非常的少,所以要訓練自己的解題能力。 多唸書多寫程式,會有很大的幫助。當然, 和同事討論更快。
***工作中的難題
我覺得工作裡比較困難的,反而不是程式本身,有一種情況是溝通問題,例如你的程式架構在別人的基礎上,需要別人提供API的修改,但是別人不願意改。另一種情況是時間太少,比方說要三個月才能夠完成的工作,壓縮到只有一個月。以上這兩種情況,在我們公司幾乎天天都會發生,雖然都是管理的問題,我都會告知主管,但是往往也沒有其他方法。
我們很難要求在完美的情況下工作,比方說別人交給你的時間都是準時的,如果有這樣子的工作環境,那表示你交給別人的時間也是準時的,那一定是一個要求很高的公司。在不完美的環境下,要盡力的把事情做好,這就是我每天的工作挑戰。
***不招人忌是庸才
最近體會到的事情,是就算做的最好, 還是會有很多的困難和挫折。比方說會受到其他部門的攻擊。有句話說, 不遭人忌是庸才,我目前還沒有想到很好的方法可以解決這種問題,其實我已經很低調,還是沒有辦法避免。只能放寬心去上班,工作還是以實力為主。
裝了一下,速度意外的好
太棒了
這一篇寫的很好很簡單,抄錄如下
由於有時會將資訊儲存下來,等著下次程式開啟時使用。以下教學怎麼記錄資訊在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
因為實在是寫的太好了,所以我貼過來
static 靜態 是個很奇妙的 關鍵字
早在 哈囉,世界 的時候就看到 static void Main() 這個 加了 static 關鍵字的方法
但是在真正了解 static 的意義卻又是很久以後的事了
最基本 也大家都知道的是
靜態的成員 不需要實體(Instance) 就能進行訪問
非靜態的成員 必須 new 一個 實體(Instance) 才能進行訪問
但這不算解釋 反而是混亂的開始
在單一使用者 單一執行 簡單功能 的情況下 這2種寫法 跑的結果一模一樣
這時就會有人覺得 那就都用靜態就好了呀 不用 new 多方便
但是隨即就嚐到苦頭 因為 靜態並非 沒有實體 而是只有一個實體 在程式執行之初就建立 並佔用記憶體位置 而且一直存在
當程式用上一堆靜態成員的時候 就造成不必要的記憶體浪費
但是現在硬體都不錯 也許這隱藏殺機不是那麼明顯 但是另一個問題就頭大囉
那就是牽一髮而動全身 靜態成員是唯一的 只要是宣告成 static 且同名的成員 都是共用一區記憶體位置
即使你這麼做
雖然 new 了三個物件 但是只要設定其中一個 其他三個 也會跟著改變
相對於 變數 屬性 這種顯而易見的差異 靜態方法 跟 非靜態方法 就顯得有些曖昧
靜態方法 屬於 類別所有
非靜態方法 屬於 實體所有
靜態方法 只能以類別名叫用 即使是 非靜態類別
非靜態方法 只能以實體叫用 所以 靜態類別 內無法有 非靜態方法 (靜態類別內一切都是靜態的)
從執行效能來看 靜態方法 比較好 因為是共用的 省去建立 跟 銷毀 物件的效能
但是也代表 靜態方法 永遠存在 不論這方法 會不會被執行
即使這樣說也很難判斷到底何時要用 靜態方法 何時不用
但是如果從物件導向的角度 - 封裝 出發 就很明確
例如一個公開的類別的 公開靜態方法 跟 公開非靜態方法 就有意義上的不同
公開的類別的公開靜態方法 即使不屬於此類別 也能叫用 因為都是公開的
公開的類別的公開非靜態方法 卻只能是 屬於此類別的 實體 才能叫用
例如一個公開類別名叫 男人 有個方法叫 站著小便
如果他是 非靜態方法 那麼可以確定 只有男人可以站著小便
如果他是 靜態方法 那就好玩了 就算是女人類別 也能 執行 男人.站著小便() 方法
好吧我知道這例子很鳥 或許真的有女人喜歡站著小便?!
那再舉一例吧 跟錢有關的 都比較有深刻體驗
例如一個公開類別名叫 我 有個方法叫 花光我的積蓄當月光仙子
如果他是 非靜態方法 那麼可以確定 只有我可以花光我的積蓄當月光仙子
如果他是 靜態方法 那就好玩了 就算是路人類別 也能 執行 我.花光我的積蓄當月光仙子() 方法
然後我的薪水就被花光了 而且花光的人 還不是我
WTF,怎麼每個聽起來都很可怕 那又什麼時候該用 靜態方法?
例如一個公開類別名叫 學生 有個方法叫 作弊
如果他是 靜態方法 那真棒 誰都可以幫助學生作弊
如果他是 非靜態方法 那有點糟 學生只能自立自強 備妥小抄望遠鏡
好吧我知道這例子很鳥 鼓吹作弊 違反社會善良風俗
例如一個公開類別名叫 我 有個方法叫 叫我起床
如果他是 靜態方法 那真棒 誰都可以叫我起床
如果他是 非靜態方法 那有點糟 只有我可以叫我自己起床 沒人幫的了我
原始網頁
http://weisnote.blogspot.com/2012/08/static.html
叫出工作管理員,把explorer.exe結束掉,然後再到工作管理員的 [檔案]=>[新工作]
輸入explorer,然後按[確定],就可以恢復正常了
來源
https://stackoverflow.com/questions/8158007/how-to-jump-the-program-execution-to-a-specific-address-in-c
21
|
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 (
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. |
#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
#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);
#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;
}
文章來源
http://blackcat12573.blogspot.tw/2013/09/linux-device-driver-ioctl-copytouser.html
來源:
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->read、fops->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 的參數 arg、fops->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 命令:,
若 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
來源
http://blog.logan.tw/2013/01/linux-driver.html
LibCurl supports URL transfer over HTTPS
protocol. In this post we’ll use LibCurl to download a webpage over HTTPS
protocol. 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.
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 SSL
certificte presented by peer.
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/
最近在做使用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):指定头文件的文件夹地址
整理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
來源
http://wdpsestea.blogspot.tw/2016/02/inkscape091.html
QT的正規表示法應用看官網說明就有了。
http://doc.qt.io/qt-5/qregularexpression.html
轉貼下面的文章,這篇文章非常的清楚好懂。
http://blog.kkbruce.net/2012/02/javascript-regular-expression.html#.Vw8SG_l97IU
名稱 | 說明 |
---|---|
\n | 換行符號 |
\r | Enter |
\t | Tab |
\xHex | 16進位ASCII |
\xOct | 8進位ASCII |
\符號 | 轉義,讓符號只是符號,無RE作用 |
名稱 | 說明 |
---|---|
[abc] | 代表英文a、b、c |
[a-z] | 代表26個英文小寫 |
[A-Z] | 代表26個英文大寫 |
[0-9] | 代表數字0到9 |
[a-zA-Z] | 代表所有大小寫英文 |
[^abc] | 除了a、b、c以外任何字元 |
- | 英文或數字的一個範圍 |
[^] | 在[]裡的^為排除的意思 |
名稱 | 說明 |
---|---|
\w | [0-9a-zA-Z_],任何英數字和底線 |
\W | [^0-9a-zA-Z_],也就是^\w的意思 |
\d | [0-9],任何數字 |
\D | [^0-9],也就是^\w的意思 |
\s | 比對空格,空白字元(space)、tab、換行字元、return/enter |
. | .(點)比較任何字元,換行字元(newline)除外 |
1 |
var reName = /pattern/[g|i|gi]; |
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.$/ |
名稱 | 說明 |
---|---|
^ | 比對字串開頭 |
$ | 比較字串結尾 |
1 |
// 需要指定「出現次數」,例如身分證 |
2 |
// A123456789,第一碼為英文,第二碼為男女,3-9碼為數字 |
3 |
var reID = /^[a-zA-Z]{1}[1-2]{1}[0-9]{8}/; |
名稱 | 說明(次數) |
---|---|
? | 0或1次 |
* | 0或多次 |
+ | 1或多次 |
{n} | 出現n次 |
{n,} | 至少n次 |
{n,m} | n到m次 |
( ) | 集合字元或/和中介字元,成為子樣式 |
1 |
// 定義過濾條件 |
2 |
var regex = /^\d{5}/$; |
3 |
// 使用test()測試是否符適合條件 |
4 |
if (!regex.test(inputField.Value)) |
5 |
... |
1 |
var objRE = new RegExp( "pattern字串" , "g|i|gi" ); |
1 |
objRE.test(strValue); |
1 |
String.match(objRE); |
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); |
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/
QT += sql
QT += sql