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

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

 

來源

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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(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 發表在 痞客邦 PIXNET 留言(0) 人氣()

來源

http://leedase.blogspot.tw/2014/04/link-fatal-error-lnk1123-coff.html

真的有效!!

 

LINK : fatal error LNK1123: 轉換成 COFF 時失敗: 檔案無效或損毀

 
VS 不能編譯?

這個問題前幾天我發生過

突然不能編譯了,讓我緊張了一下 , 上網查果然也有人跟我一樣的情況

原因是我 的電腦 WIN7 x64, Visual Studio 2010, Visual Studio 2012 都有
 
所以按照人家提出的方法, 確定是可以解決的. 以下兩個資料夾, 都同時存在一個檔案 cvtres.exe,
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin
C:\Windows\Microsoft.NET\Framework\v4.0.30319
只要把 C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin 裡面的cvtres.exe 改名字, 問題就解決了, 因為這個版本是 10.00.xxx, 比較老的.
 
查詢的網址為:
http://xiaolaba.wordpress.com/2013/09/01/link-fatal-error-lnk1123-%E8%BD%89%E6%8F%9B%E6%88%90-coff-%E6%99%82%E5%A4%B1%E6%95%97-%E6%AA%94%E6%A1%88%E7%84%A1%E6%95%88%E6%88%96%E6%90%8D%E6%AF%80/

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

下面寫個很簡單可以改變按鈕外觀的方法

 

到designer裡按右鍵,變更樣式表即可

 

 

 

Another way, to edit it's StyleSheets. It's easy!

 

 

 

#include <QApplication>
#include <QPushButton>
#include <QFont>
#include <QMenu>
#include <QLabel>
 
int main(int argc, char *argv[]) {
 
 
     QApplication app(argc, argv);
 
     QPushButton *btn = new QPushButton("Close");
     btn->setWindowTitle("Signal & Slot");
     btn->setFont(QFont("Courier", 18, QFont::Bold));
     btn->resize(250, 50);
     btn->setStyleSheet("background-color: yellow");
 
     QObject::connect(btn, SIGNAL(clicked()), &app, SLOT(quit()));
 
     btn->show();
 
 
     return app.exec();
}
 
 
 

 

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

原文 

http://www.heerengandhi.com/2009/07/29/firefox-icon-went-missing-in-windows-7-heres-a-fix/

 

照著做之後,Windows 7下的Thunderbird的圖標就恢復正常了。

轉貼如下

 

Firefox Icon went missing in Windows 7? Here’s a Fix

After installing the latest and greatest Mozilla Firefox 3.5 in Windows 7 (RC 64-bit) I noticed that after a while the icon went missing. Now Firefox was still working correctly, and when I checked the icon properties the icon was still present. But for some strange reason it wouldn’t show up in on my Desktop, my Start Menu, or my Taskbar, I would just see a broken icon.

The resolution? Rebuilding the Windows 7 Icon Cache.

Follow these directions:

  1. Close all folder windows that are currently open.
  2. Launch Task Manager using the CTRL+SHIFT+ESC key sequence, or by running taskmgr.exe
  3. In the Process tab, right-click on the Explorer.exe process and select End Process
  4. Click the End process button when asked for confirmation.
  5. From the File menu of Task Manager, select New Task (Run…)
  6. Type CMD.EXE, and click OK
  7. In the Command Prompt window, type the commands one by one and press ENTER after each command:CD /d %userprofile%\AppData\Local
    DEL IconCache.db /a
    EXIT
  8. In Task Manager, click File, select New Task (Run…)
  9. Type EXPLORER.EXE, and click OK.

Your icons should be as good as new!

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

今天發現了好文章,解決了我的問題。

分享如下

 

軟體套件發行的方法:大型專案開發適用,使用 C++ 語言
 1、下載 Qt5.5 
  - 網頁 http://www.qt.io/download-open-source/#section-2
  - 找 Windows Host 中的 Qt 5.5.1 for Windows 32-bit (MinGW 4.9.2, 1.0 GB)  只有 32位元版
   - 檔案:qt-opensource-windows-x86-mingw492-5.5.1.exe
 2、下載 Qt Installer Framework
  - 網頁 http://www.qt.io/download-open-source/#section-2
  - 找 Other downloads 中的 Qt Installer Framework
   - 檔案:Qt Installer Framework Opensource 2.0.1.exe
 3、安裝 qt-opensource-windows-x86-mingw492-5.5.1.exe
 4、安裝 Qt Installer Framework Opensource 2.0.1.exe
 5、開啟 Qt Creator (Community)
 6、開啟現有專案
  - C:\Qt\Qt5.5.1\Examples\Qt-5.5\opengl\2dpainting\2dpainting.pro
  - 按下 Configure Project ,會生一個 C:\Qt\Qt5.5.1\Examples\Qt-5.5\opengl\2dpainting\2dpainting.pro.user 以後就不會再問了
  - 建置 -> 執行(或是按下左下方的綠色 Play 按鈕)
  - 會在 C:\Qt\Qt5.5.1\Examples\Qt-5.5\opengl\build-2dpainting-Desktop_Qt_5_5_1_MinGW_32bit-Debug\debug 生出我們要的 2dpainting.exe
 7、把他 copy 出來,或是把其他的 *.o *.cpp 殺了
 8、開一個命令提示字元視窗,加持 Qt 要用的 path
  - 直接執行 C:\Windows\System32\cmd.exe /A /Q /K C:\Qt\Qt5.5.1\5.5\mingw492_32\bin\qtenv2.bat
  - 或 下指令 set PATH=C:\Qt\Qt5.5.1\5.5\mingw492_32\bin;C:\Qt\Qt5.5.1\Tools\mingw492_32\bin;%PATH%
  - 或點選開始選單裡的 Qt 5.5.1 > 5.5 > MinGW 4.9.2 (32-bit) > Qt 5.5 for Desktop (MinGW 4.9.2 32 bit) 項目
 9、切換到專案發佈的目錄: cd C:\Qt\Qt5.5.1\Examples\Qt-5.5\opengl\build-2dpainting-Desktop_Qt_5_5_1_MinGW_32bit-Debug\debug
10、執行 windeployqt 2dpainting.exe ,幫我們帶出 DLL 們
11、這整個 C:\Qt\Qt5.5.1\Examples\Qt-5.5\opengl\build-2dpainting-Desktop_Qt_5_5_1_MinGW_32bit-Debug\debug 就是綠色套件了
12、其實從項次 7 開始,我研究了二天,終於看到異國年輕人的教材,聽得半懂,看得全懂,有興趣可以去看看 Tutorial Qt Installer Frameworkhttps://youtu.be/pXRwgEP_q-Y 
13、最後就是用 Qt Installer Framework 去打包成安裝檔,詳解請閱聽上述 youtube 影片

這樣,我就可以開始拼湊範例程式,開發我的「桌面應用程式」了。或許「手機應用程式」也能陸續完成。

 

來源

http://phorum.study-area.org/index.php/topic,71475.msg343309.html#msg343309

 

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

問題描述

1.png 

2.png 

解決"無法加入成員變數至具有ID IDC_STATIC的控制項" Visual C++ 2015

如下面寫的,把IDC_STATIC改名就可以了。


https://social.msdn.microsoft.com/Forums/vstudio/e...

What error did you get?   What is the type of mLabel?  

First, right click on the static control and select 'Properties.'  If the control ID is IDC_STATIC you must edit it so it has a unique value, like IDC_MY_LABEL.

mLabel should be created by right clicking on the static control in the dialog editor and selecting 'Add Variable',  then selecting 'Control Variable'. The result will be a dialog member variable CStatic mLabel.  mLabel.SetWindowText should then work.

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

官網的文章就很好用了。

寫在這裡

Visual Studio 中的 C++ 使用者入門

https://msdn.microsoft.com/zh-tw/library/jj620919....

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

解決"找不到或無法開啟 PDB 檔案"在Visual C++ 2015 Community (VC 2015)

上網找了一下都是舊文章

新的選項的位置不同。

解決方法

偵錯-->選項

1.png


偵錯-->符號-->把Microsoft符號伺服器打勾)

符號.png 


如下圖,已可以正常偵錯。

ConsoleApplication1.exe' (Win32): 已載入 'D:\xxxxxxxxxx\VC\ConsoleApplication1\x64\Debug\ConsoleApplication1.exe'。已載入符號。

ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\ntdll.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\kernel32.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\KernelBase.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\msvcp140d.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\vcruntime140d.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\ucrtbased.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\api-ms-win-core-timezone-l1-1-0.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\api-ms-win-core-file-l2-1-0.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\api-ms-win-core-localization-l1-2-0.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\api-ms-win-core-synch-l1-2-0.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\api-ms-win-core-processthreads-l1-1-1.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\api-ms-win-core-file-l1-2-0.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\advapi32.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\msvcrt.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\sechost.dll'。已載入符號。
ConsoleApplication1.exe' (Win32): 已載入 'C:\Windows\System32\rpcrt4.dll'。已載入符號。
'[3604] ConsoleApplication1.exe' 程式以返回碼 0 (0x0) 結束。


3.png 

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

作者: bur (角落) 看板: AntiVirus
標題: [求救] IE8 新索引標籤 變成 babylon search
時間: Wed Sep 14 08:43:31 2011

系統:win 7
已經掃毒過,找不到病毒
也在控制台移除了babylon toolbar 執行程式
網際網路的工具裡面的附加管理也移除了babylon search

也下載了惡意程式移除掃描
網址的about:tabs的登錄值也跟預設值一樣沒有其他奇怪的網址

該怎麼處理!!!> <


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

→ ringshin:網際網路選項理的最下方TAB進去回復預設應該就好了    

這是正解,我剛才測試有用

 

 

 

 

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

1 23
找更多相關文章與討論