顯示具有 C Code 標籤的文章。 顯示所有文章
顯示具有 C Code 標籤的文章。 顯示所有文章

2012年3月8日 星期四

判斷檔案是否存在

使用函數 
    int access(const char *filename, int amode);
apmode為0時是檢查檔案的存在性


access可以檢查檔案其他屬性:
06 檢查讀寫權限
04 檢查讀權限
02 檢查寫權限
01 檢查執行權限
00 檢查檔案存在


#include<stdio.h>
main()
{
    printf("access=%d\n",access("/tmp/file",0));
    //if 0 檔案存在
    //if -1檔案不存在
} 

pthread使用說明

轉自:http://www.cnblogs.com/xianghang123/archive/2011/08/11/2134927.html


linux下C/C++,多線程pthread 


 ·線程創建 


  函數原型:int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void),void *restrict arg); 


  返回值:若是成功建立線程返回0,否則返回錯誤的編號。 


  形式參數:pthread_t *restrict tidp要創建的線程的線程id指針;const pthread_attr_t *restrict attr創建線程時的線程屬性;void* (start_rtn)(void)返回值是void類型的指針函數;void *restrict arg start_rtn的形參。 


  ·線程掛起:該函數的作用使得當前線程掛起,等待另一個線程返回才繼續執行。也就是說當程序運行到這個地方時,程序會先停止,然後等線程id為thread的這個線程返回,然後程序才會斷續執行。 


  函數原型:int pthread_join( pthread_t thread, void **value_ptr); 


  參數說明如下:thread等待退出線程的線程號;value_ptr退出線程的返回值。 


  ·線程退出 


  函數原型:void pthread_exit(void *rval_ptr); 


  ·獲取當前線程id 


  函數原型:pthread_t pthread_self(void); 


  ·互斥鎖 


  創建pthread_mutex_init;銷毀pthread_mutex_destroy;加鎖pthread_mutex_lock;解鎖pthread_mutex_unlock。 


  ·條件鎖 


  創建pthread_cond_init;銷毀pthread_cond_destroy;觸發pthread_cond_signal;廣播pthread_cond_broadcast S;等待pthread_cond_wait。  


  ·正確處理Linux平台下的線程結束問題 


  在Linux平台下,當處理線程結束時需要注意的一個問題就是如何讓一個線程善始善終,讓其所占資源得到正確釋放。在Linux平台默認情況下,雖然各個線程之間是相互獨立的,一個線程的終止不會去通知或影響其他的線程。但是已經終止的線程的資源並不會隨著線程的終止而得到釋放,我們需要調用pthread_join() 來獲得另一個線程的終止狀態並且釋放該線程所占的資源。








【用C】


/* example.c*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void thread(void)
{
int i;
for(i=0;i<3;i++){
sleep(1);
printf("This is a pthread.\n");}
}
int main(void)
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *) thread,NULL);
if(ret!=0){
printf ("Create pthread error!\n");
exit (1);
}
for(i=0;i<3;i++){
printf("This is the main process.\n");
sleep(1);
}
pthread_join(id,NULL);
return (0);
}





編譯命令 gcc -o example example.c -lpthread


注:【1】pthread 庫不是 Linux 系統默認的庫,連接時需要使用靜態庫 libpthread.a,所以在使用pthread_create()創建線程,以及調用 pthread_atfork()函數建立fork處理程序時,需要鏈接該庫。


      【2】還要添加頭文件pthread.h


      【3】因為C庫自帶sleep,所以可以不添加unistd.h頭文件





【用C++】


/* example.cpp*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *thread(void *ptr)
{
int i;
for(i=0;i<3;i++){
sleep(1);
printf("This is a pthread.\n");}
}
int main(void)
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,thread,NULL);
if(ret!=0){
printf ("Create pthread error!\n");
exit (1);
}
for(i=0;i<3;i++){
printf("This is the main process.\n");
sleep(1);
}
pthread_join(id,NULL);
return (0);
}





編譯鏈接命令 g++ -o example2 example.c -lpthread





【注】 標亮部分,注意C++開發時與C的區別,解釋如下:


我們注意在Posix定義建立線程函數的原型:
extern int pthread_create (pthread_t *__restrict __threadp,
                           __const pthread_attr_t *__restrict __attr,
                           void *(*__start_routine) (void *),
                           void *__restrict __arg) __THROW;
這個call中的第三個參數是載入一個函數,這個函數有一個參數可以傳入,返回一個 通用指針。
我們再來看看原來函數中是怎樣調用這一原型的,基本上就是類似一下的調用方式:
(void *) thread 或是 (void *) &thread


這個表達式的含義:取一個指向函數main_thread的指針,然後將其轉換為一個通用指針。
這就是說顯然上述兩個事情並非同一個事情,故而正確的調用方式是
ret=pthread_create(&id,NULL,thread,NULL);
處理函數的定義如下:
void *thread(void *ptr)
值得注意的是在gcc編譯時不會出錯,但是用g++就會有問題:invalid conversion from `void*' to `void*(*)(void*),究其原因就是C語言編譯器允許隱含性的將一個通用指針轉換為任意類型的指針,而C++不允許。

2012年3月2日 星期五

輸出u32/u64格式

d, lx, ld, lu, 這幾各都是輸出32位元
hd, hx, hu, 這幾各都是輸出16位元
hhd, hhx, hhu, 這幾各都是輸出8位元
lld, ll, llu, llx, 這幾各都是輸出65位元

printf( "%llu ",.....)
%llu   是64位元無符號
%llx   是64位元16進制

2012年1月6日 星期五

信號處理

轉自:http://blog.csdn.net/ljx0305/article/details/2904056


SIGHUP       终止进程    终端线路挂断
SIGINT         终止进程    中断进程
SIGQUIT      建立CORE文件终止进程,并且生成core文件
SIGILL         建立CORE文件      非法指令
SIGTRAP     建立CORE文件      跟踪自陷
SIGBUS       建立CORE文件      总线错误
SIGSEGV     建立CORE文件      段非法错误
SIGFPE        建立CORE文件      浮点异常
SIGIOT         建立CORE文件      执行I/O自陷
SIGKILL       终止进程    杀死进程
SIGPIPE       终止进程    向一个没有读进程的管道写数据
SIGALARM   终止进程    计时器到时
SIGTERM     终止进程    软件终止信号
SIGSTOP     停止进程    非终端来的停止信号
SIGTSTP     停止进程    终端来的停止信号
SIGCONT     忽略信号    继续执行一个停止的进程
SIGURG       忽略信号    I/O紧急信号
SIGIO          忽略信号    描述符上可以进行I/O
SIGCHLD     忽略信号    当子进程停止或退出时通知父进程
SIGTTOU     停止进程    后台进程写终端
SIGTTIN       停止进程    后台进程读终端
SIGXGPU     终止进程    CPU时限超时
SIGXFSZ      终止进程    文件长度过长
SIGWINCH   忽略信号    窗口大小发生变化
SIGPROF      终止进程    统计分布图用计时器到时
SIGUSR1      终止进程    用户定义信号1
SIGUSR2      终止进程    用户定义信号2
SIGVTALRM 终止进程    虚拟计时器到时


1) SIGHUP 本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控 制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端 不再关联.
2) SIGINT 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出 
3) SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl-)来控制. 进程在因收到 SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号. 
4) SIGILL 执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号. 
5) SIGTRAP 由断点指令或其它trap指令产生. 由debugger使用. 
6) SIGABRT 程序自己发现错误并调用abort时产生. 
7) SIGIOT 在PDP-11上由iot指令产生, 在其它机器上和SIGABRT一样. 
8) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错. eg: 访问一个四个字长的整数, 但其地址不是4的倍数. 
9) SIGFPE 在发生致命的算术运算错误时发出.不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误. 
10) SIGKILL 用来立即结束程序的运行. 本信号不能被阻塞, 处理和忽略. 
11) SIGUSR1 留给用户使用.
12) SIGSEGV 试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据. 
13) SIGUSR2 留给用户使用. 
14) SIGPIPE Broken pipe.
15) SIGALRM 时钟定时信号, 计算的是实际的时间或时钟时间. alarm函数使用该信号. 
16) SIGTERM 程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理. 通常用来要求程序自己正常退出. shell命令kill缺省产生这个信号. 
17) SIGCHLD 子进程结束时, 父进程会收到这个信号. 
18) SIGCONT 让一个停止(stopped)的进程继续执行. 本信号不能被阻塞. 可以用 一个handler来让程序在由stopped状态变为继续执行时完成特定的 工作. 例如, 重新显示提示符. 
19) SIGSTOP 停止(stopped)进程的执行. 注意它和terminate以及interrupt的区别:该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略. 
20) SIGTSTP 停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号.
21) SIGTTIN 当后台作业要从用户终端读数据时, 该作业中的所有进程会收到SIGTTIN信号. 缺省时这些进程会停止执行. 
22) SIGTTOU 类似于SIGTTIN, 但在写终端(或修改终端模式)时收到. 
23) SIGURG 有"紧急"数据或out-of-band数据到达socket时产生. 
24) SIGXCPU 超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/改变. 
25) SIGXFSZ 超过文件大小资源限制. 
26) SIGVTALRM 虚拟时钟信号. 类似于SIGALRM, 但是计算的是该进程占用的CPU时间. 
27) SIGPROF 类似于SIGALRM/SIGVTALRM, 但包括该进程用的CPU时间以及系统调用的 时间. 
28) SIGWINCH 窗口大小改变时发出. 
29) SIGIO 文件描述符准备就绪, 可以开始进行输入/输出操作. 
30) SIGPWR Power failure.


有两个信号可以停止进程:SIGTERM和SIGKILL。 SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。在某些情况下,假如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。


对于SIGKILL信号,进程是不能忽略的。这是一个 “我不管您在做什么,立刻停止”的信号。假如您发送SIGKILL信号给进程,Linux就将进程停止在那里。

2011年12月31日 星期六

C 語言基本資料型態

short    -> 2 Byte -> -32768 ~ 32767
int         -> 4 Byte -> -2147483648 ~ 2147483647
long     -> 4 Byte -> -2147483648 ~ 2147483647
float     -> 4 Byte ->  1.2*10-38~3.4*10+38 //單精確浮點數,有效位數7位數
double-> 8 Byte ->  2.2*10-308~1.8*10+308 //單精確浮點數,有效位數7位數


unsigned short -> 2 Byte -> 0 ~ 65535
unsigned int      -> 4 Byte -> 0~4294967295
unsigned long  -> 4 Byte -> 0~4294967295

2011年12月24日 星期六

Linux c argc argv 使用方式

//argc 表示輸入幾個參數 
//argv 表示輸入參數值 argv[0],argv[1]...等
//getopt 預設參數哪些值 



#include <stdio.h>
#include <unistd.h>

int main(int argc,char **argv)
{
        int cmd;
        while((cmd=getopt(argc,argv,"A:B:"))!=-1)
        {
                switch(cmd)
                {
                        case 'A':
                                printf("command_A=%s\n",optarg);
                                break;
                        case 'B':
                                printf("command_B=%s\n",optarg);
                                break;
                        default:
                                printf("Unknown argument!!\n");
                                break;
                }
        }
}

2011年12月14日 星期三

Linux c Split 用法

#include <stdio.h>
#include <string.h>


int main ()
{
 char str[] ="a b c d*e";
 const char *split = " ";
 char *p;
 int i=0;
 p = strtok (str,split);
 while(p!=NULL)
 {
  if (i==1)
   printf ("%s\n",p);
   i++;
  p = strtok(NULL,split);
 }
 return 0;
} 

linux c 取得 Mac address

#include <stdio.h>
#include <string.h> /* for strncpy */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>

int main(void) {
    int fd;
    struct ifreq ifr;
    char mac[20];
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    ifr.ifr_addr.sa_family = AF_INET;
    strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
    ioctl(fd, SIOCGIFHWADDR, &ifr);
    close(fd);
    sprintf(mac,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
             (unsigned char)ifr.ifr_hwaddr.sa_data[0],
             (unsigned char)ifr.ifr_hwaddr.sa_data[1],
             (unsigned char)ifr.ifr_hwaddr.sa_data[2],
             (unsigned char)ifr.ifr_hwaddr.sa_data[3],
             (unsigned char)ifr.ifr_hwaddr.sa_data[4],
             (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
    printf("eth0 mac address:%s\n", mac);
    return 0;
}

2011年12月4日 星期日

enum(列舉)說明

列舉在 C 語言為一種特別的型態,其內的識別字會是逐項遞增的整數常數.

enum weeks {SUN, MON, TUE, WED, THU, FRI, SAT};
結果如下:
SUN=0,MON=1,TUE=2,WED=3,THU=4,FRI=5,SAT=6
編譯器會自動給 SUN 整數 0 的值,然後依次遞增, MON 為 1 , TUE 為 2 ... 等。也可以先給值,如下:
enum weeks {SUN=1, MON, TUE, WED, THU, FRI, SAT};
這樣 JAN 的值會是 1 ,然後依次遞增。

2011年10月17日 星期一

linux C - popen() function


#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
描述
popen() 函數使用建立管道的方式, 並使用 shell.  因為管道是被定義成單向的, 所以 type參數只能定義為 read 或 write, 不能是read/write 兩者同時定義, result stream也只可read或write.
command 參數是一個string pointer, 指向的是一個以null 為結尾的字串,這個字串包含一個shell命令. 這個命令被送到 /bin/sh 以 -c 參數執行,即由shell來執行. type 參數也是一個指向以null為結尾的string pointer, 這個字串必須是'r'或者'w'來定義是讀還是寫.
popen() 函數的回傳值是一個普通的標準I/O stream,它只能用 pclose() 函數來關閉,而不是 fclose().函數.
像這個流的寫入被轉化為對command命令的標準輸入;而command命令的標準輸出則是和調用 popen(),函數的進程相同,除非這個被command命令自己改變.相反的,讀取一個“被popen了的”流,就相當於讀取command命令的標準輸出,而command的標準輸入則是和調用 popen,函數的進程相同.
注意, popen 函數的輸出流默認是被全緩衝的.
pclose 函數等待相關的進程結束並返回一個command命令的退出狀態,就像 wait4 函數一樣
示例:
#include <stdio.h>
int main(int argc, char *argv[]) {
    char buf[128];
    FILE *pp;
    if( (pp = popen("ls -l", "r")) == NULL ) {
        printf("popen() error!\n");
        retur;
    } 
    while(fgets(buf, sizeof buf, pp)) {
        printf("%s", buf);
    }
    pclose(pp);
    return 0;
}

2011年10月4日 星期二

檢查網路Port是否Link

PS.have to install ethtool tool



#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <fcntl.h>
#include  <errno.h>
#include  <sys/ioctl.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <linux/if.h>


typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned char u8;


#include  <linux/sockios.h>
#include  <linux/ethtool.h>


int main()
{
    int skfd;
    struct ifreq ifr;
    struct ethtool_value edata;
    edata.cmd = ETHTOOL_GLINK;
    edata.data = 0;
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
    ifr.ifr_data = (char *) &edata;
    if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 )) == 0)
        return -1;
    if(ioctl( skfd, SIOCETHTOOL, &ifr ) == -1)
    {
        close(skfd);
        return -1;
    }
    close(skfd);
    printf("========%d\n",edata.data);
}

2011年9月5日 星期一

malloc

C 語言標準函數庫分類導覽 - stdlib.h malloc()
stdlib.h 的函數 malloc() 用來做動態記憶體配置,產生動態的記憶體空間,需要一個利用 sizeof 計算所佔記憶體空間大小的參數。
若建立成功, malloc() 回傳指向該空間的指標,否則回傳 NULL 。


以下程式利用函數 malloc() 建立新記憶體空間
#include <stdlib.h>
#include <stdio.h>  
int main(void)
{
     int *nPtr; 
     nPtr = malloc(sizeof(int));   
     if (nPtr == NULL) {
         printf("建立記憶體空間失敗\n");    
     }    
     else {
         printf("建立記憶體空間成功\n");
     }
     return 0;
}  

memset

string.h 的函數 memset() 將某一記憶體區段的前 n 個字元全部設定為某一字元。
以下程式將字串 s 全部設成 'n'
#include <stdio.h>
#include <string.h>  
int main(void)
{
     char s[] = "congratulation";
     printf("%s\n", memset(s, 'n', 13));
     return 0;    
}  

字串相加

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *string_concat(char*str1, char*str2)
{
   int length=strlen(str1)+strlen(str2)+1;
   char *result = (char*)malloc(sizeof(char) * length);
   strcpy(result, str1); 
   strcat(result, str2); 
   return result;  
} 
int main()
{  
   char *a="123456"; 
   char b[8]="abcde";  
   char *c=string_concat(a,b); 
   printf("%s\n",c);  
   return 0; 
}




#另一種方式
char aa[8]="aaa";
char bb[8]="bbb";
char cc[8];
sprintf(cc+0,"%s",aa);
sprintf(cc+3,"%s",bb);