关于多线程、安装信号、长跳转、数据结构等的例子
2016-05-12 22:20
417 查看
#include <stdio.h> #include <stdlib.h> #include <unistd.h>//告诉驱动程序pid以及系统调用fcntl的头文件 #include <sys/ioctl.h> #include <sys/types.h>//告诉驱动程序pid #include <sys/stat.h> #include <fcntl.h>//系统调用fcntl的头文件,文件控制定义 #include <sys/select.h> #include <sys/time.h> #include <errno.h>//错误号定义 #include <poll.h> #include <stdint.h> #include <asm/types.h> #include <sys/mman.h> #include <string.h> #include <malloc.h> #include <termios.h> //PPSIX 终端控制定义 #include <signal.h>//调用signal函数的头文件 #include <pthread.h>//多线程程序设计需要 #include <setjmp.h> //goto语句只能在函数内部跳转,而setjmp和longjmp函数可以在函数之间或不同文件之间跳转 #include "uart.h" //<>为系统头文件,""为自定义头文件 #include "spiRf2401.h" #include "ArrayList.h" #include "ArrayQueue.h" #include "doubleLinkedList.h" #include "LinkedList.h" #include "LinkedStack.h" #include "LinkedQueue.h" /*********************************************关于延时函数********************************************************* Linux中的延时函数: (1)应用层: sleep(1);1S延时 usleep(1);1US延时,1000US=1MS,1000MS=1S (2)内核层: #include <linux/delay.h> void ndelay(unsigned long nsecs); 纳秒级 void udelay(unsigned long usecs); 微秒级 void mdelay(unsigned long msecs); 毫秒级 ****************************************************************************************************************/ /***********************************************typedef和define************************************************** typedef和define的区别: (1)#define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不管含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错;而typedef是在编译时处理的。它在自己的作用域内给一个已经存在的类型一个别名。 (2)typedef int * ptr与#define ptr int *的区别:作用都是用ptr代表int * ,但是二者不同,正如前面所说 ,#define在预处理时进行简单的替换,而typedef不是简单替换 ,而是采用如同定义变量的方法那样来声明一种类型。#define ptr int * ;ptr a, b; 相当于int * a, b只是简单的宏替换。typedef int* ptr;ptr a, b; a, b 都为指向int的指针,typedef为int* 引入了一个新的助记符,但是这个时候,如果使用stuct Node* a,b;时编译器会报错(意图是定义两个结构体指针变量),正确的定义方式为stuct Node* a,*b;。 (3)typedef int * pint与#define PINT int * const pint p;//p不可更改,但p指向的内容可更改 const PINT p;//p可更改,但是p指向的内容不可更改。 pint是一种指针类型,const pint p 就是把指针给锁住了,p不可更改而const PINT p 是const int * p, 锁的是指针p所指的对象。 (4)#define不是语句,不要在行末加分号,否则会连分号一块置换。 (5)关于typedef和define的作用域 1) 不管是typedef还是define,都不能在定义之前使用; 2) typedef受函数范围影响,而define不受; 3) 不管是typedef还是define,其作用域都不会扩展到别的文件,即使是同一个程序的不同文件,也不能互相使用。 (6)typedef和结构体 注意:在C++中struct 的成员默认是公有的,而类的成员默认是私有的。struct 和 class 在其他方面是功能相当的。 struct { int num ; }stu1; //只能在定义结构体时用一次,以后再也无法定义此结构体变量,缺乏灵活性。 struct student { int num ; }stu1; //此处定义结构体时,顺便定义了结构体变量。 typedef struct student { int num ; }stu1; //注意:此处并非结构体变量,而是结构体类型(相当于人的小名,相当于struct student) typedef struct Node { int data; pNode pNext; }*pNode; //编译出错 问题分析:C语言允许在结构中包含指向它自己的指针,可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。 解决方案: typedef struct Node { int data; struct Node *pNext; }*pNode; ****************************************************************************************************************/ /**********************************************关于Linux中内存管理************************************************* 1、linux内核管理内存空间的分配,所有程序对内存空间的申请和其他操作,最终都会交给内核来管理。 2、linux实现的是“虚拟内存系统”,对用户而言,所有内存都是虚拟的,也就是说程序并不是直接运行在物理内存上,而是运行在虚拟内存上,然后由虚拟内存转换到物理内存。 3、linux将所有的内存都以页为单位进行划分,通常每一页是4KB; 4、在对虚拟内存地址到物理内存地址进行转换时,内核会对地址的正确性进行检查,如果地址是合法的,内核就会提供对应的物理内存分页;如果是申请内存空间,内核就会检查空余的物理内存分页,并加以分配,如果物理内存空间不足,内核会拒绝此次申请; 5、使用malloc分配的内存空间在虚拟地址空间上是连续的,但是转换到物理内存空间上有可能是不连续的,因为有可能相邻的两个字节是在不同的物理分页上; ****************************************************************************************************************/ /*********************************************关于数据结构******************************************************** 1.打印的数据结构文档(包括大纲)。 2.每个源码前的注释都大概说明了每种结构和操作 3.知识结构: (1)线性结构:顺序存储ArrayList.c , 离散存储LinkedList.c 线性存储的应用:用数组实现堆栈和队列,用链表实现堆栈和队列,双链表,递归 (2)非线性结构:树和图 ****************************************************************************************************************/ void *thread1(void *str); void *thread2(void *str); void *thread3(void *str); void *thread4(void *str); void *thread5(void *str); void *thread6(void *str); int ioSignal=0; int busErrSignal=0; int segvErrSignal=0; int illSignal=0; int intSignal=0;//中断信号标记 jmp_buf buf;//长跳转参数 void my_signal_fun(int signum) { //根据C专家编程,系统并不支持在信号处理程序内部调用库函数(除非严格符合标准所限制的条件),这点必须注意。比如调用交互式I/O printf函数。 if ( signum == SIGIO ) { ioSignal = 1; } else if ( signum == SIGBUS ) { busErrSignal = 1; } else if ( signum == SIGSEGV ) { segvErrSignal = 1; } else if ( signum == SIGILL ) { illSignal = 1; } else { intSignal = 1; } } int main(void)//没有信号的时候执行主函数里面的,当捕获到信号后,执行信号函数里面的,相当于中断一下 { //安装信号 signal(SIGIO, my_signal_fun);//SIGIO表示io口有数据可以读写时将发送信号 signal(SIGBUS, my_signal_fun);//SIGBUS表示发生总线错误时调用信号处理函数 signal(SIGSEGV, my_signal_fun);//SIGSEGV表示发生段错误时调用信号处理函数,这里如果不安装,当本程序发生段违规后,操作系统会强行干掉本进程 signal(SIGILL, my_signal_fun);//SIGILL表示发生非法指令异常时将发送信号,调用信号处理函数 signal(SIGINT, my_signal_fun);//SIGINT表示发生中断时将发送信号,调用信号处理函数 比如按ctrl + c printf("\n"); switch ( setjmp(buf) ) { case 0: printf("first time in main\n"); break; case 1: printf("back in main\none SIGIO happen\nreturn 0\n"); return 0; case 2: printf("back in main\none SIGBUS happen\nreturn 0\n"); return 0; case 3: printf("back in main\none SIGSEGV happen\nreturn 0\n"); return 0; case 4: printf("back in main\none SIGILL happen\nreturn 0\n"); return 0; case 5: printf("back in main\none SIGINT happen\nreturn 0\n"); return 0; } /*****************************创建三条线程,并处于就绪态************************/ pthread_t pth1,pth2,pth3,pth4,pth5,pth6; int error1,error2,error3,error4,error5,error6; error1=pthread_create(&pth1,NULL,thread1,NULL); //创建线程,线程进入就绪模式 if(error1!=0) { printf("new thread1 is not create success! …\n"); return -1; } error2=pthread_create(&pth2,NULL,thread2,NULL); //创建线程,线程进入就绪模式 if(error2!=0) { printf("new thread2 is not create success! …\n"); return -1; } error3=pthread_create(&pth3,NULL,thread3,NULL); //创建线程,线程进入就绪模式 if(error3!=0) { printf("new thread3 is not create success! …\n"); return -1; } error4=pthread_create(&pth4,NULL,thread4,NULL); //创建线程,线程进入就绪模式 if(error4!=0) { printf("new thread4 is not create success! …\n"); return -1; } error5=pthread_create(&pth5,NULL,thread5,NULL); //创建线程,线程进入就绪模式 if(error5!=0) { printf("new thread5 is not create success! …\n"); return -1; } error6=pthread_create(&pth6,NULL,thread6,NULL); //创建线程,线程进入就绪模式 if(error6!=0) { printf("new thread6 is not create success! …\n"); return -1; } /*****************************创建n条线程,并处于就绪态************************/ /*如果不想阻塞主进程,可以调用pthread_detach函数*/ pthread_join(pth1,NULL);//阻塞,让处于就绪态的线程开始执行,直到线程退出 pthread_join(pth2,NULL);//阻塞,让处于就绪态的线程开始执行,直到线程退出 pthread_join(pth3,NULL);//阻塞,让处于就绪态的线程开始执行,直到线程退出 pthread_join(pth4,NULL);//阻塞,让处于就绪态的线程开始执行,直到线程退出 pthread_join(pth5,NULL);//阻塞,让处于就绪态的线程开始执行,直到线程退出 pthread_join(pth6,NULL);//阻塞,让处于就绪态的线程开始执行,直到线程退出 printf("\n"); printf("All program will end!\n"); printf("\n"); sleep(1); return 0; } //信号发生后报告 void *thread1(void *str) { printf("here is thread1\n"); int i=0; while(1) { usleep(100000); if ( 1 == ioSignal ) { ioSignal = 0; printf("now got a SIGIO signal!\n"); longjmp(buf,1); } else if ( 1 == busErrSignal ) { busErrSignal = 0; printf("now got a bus error signal!\n"); longjmp(buf,2); } else if ( 1 == segvErrSignal ) { segvErrSignal = 0; printf("now got a segmentation violation error signal!\n"); longjmp(buf,3); } else if ( 1 == illSignal ) { illSignal = 0; printf("now got a illegal instruction signal!\n"); longjmp(buf,4); } else if ( 1 == intSignal ) { intSignal = 0; printf("\n"); printf("now got a SIGINT signal!\n"); longjmp(buf,5); } else { //printf("no signal!\n"); sleep(1); //break; } } return NULL; } //线性结构中数组的存储和操作 void *thread2(void *str) { printf("here is thread2\n"); /* int i=0,val=0; struct arrayList arr; struct arrayList *pArray; pArray = &arr; init_arraylist(pArray,10); //showArrayList(&arr); addToEnd(pArray,234); addToEnd(pArray,23); addToEnd(pArray,653); addToEnd(pArray,99); addToEnd(pArray,235); addToEnd(pArray,57); showArrayList(pArray); printf("pArray->len=%d,pArray->cnt=%d\n",pArray->len,pArray->cnt); deleteElement(pArray,3,&val); showArrayList(pArray); printf("pArray->len=%d,pArray->cnt=%d,val=%d\n",pArray->len,pArray->cnt,val); insertArrayList(pArray,3,999); showArrayList(pArray); printf("pArray->len=%d,pArray->cnt=%d\n",pArray->len,pArray->cnt); inversionArrayList(pArray); showArrayList(pArray); sortArrayList(pArray); showArrayList(pArray); freeArrayList(pArray); showArrayList(pArray);//前面已经释放了pBase指针,即释放了动态分配的内存,并把pBase设为NULL,这里再使用pBase指针就会发生段错误,从而程序捕获段违规信号 */ struct structEntry { int intEntry; char charEntry[20]; struct list_head list; }; struct structEntry entry; return NULL; } void *thread3(void *str) { printf("here is thread3\n"); /* int pVal=0; struct Node* pHead ; pHead = creatLinkedList(); traverseLinkedList(pHead); printf("the list length=%d\n",lengthLinkedList(pHead)); printf("sortLinkedList\n"); sortLinkedList(pHead); traverseLinkedList(pHead); printf("insertLinkedList\n"); insertLinkedList(pHead,7,222); traverseLinkedList(pHead); printf("deleteLinkedList\n"); deleteLinkedList(pHead,1,&pVal); traverseLinkedList(pHead); printf("the list length=%d,pVal=%d\n",lengthLinkedList(pHead),pVal); freeLinkedList(pHead); traverseLinkedList(pHead); */ return NULL; } void *thread4(void *str) { printf("here is thread4\n"); /* int depth=0; int val=0; struct LinkedStack S; initStack(&S); linkedStackPush(&S,1); linkedStackPush(&S,2); linkedStackPush(&S,3); linkedStackPush(&S,4); linkedStackPush(&S,5); traverseLinkedStack(&S,&depth); printf("the LinkedListStack depth is %d\n",depth); linkedStackPop(&S,&val); traverseLinkedStack(&S,&depth); printf("the LinkedListStack depth is %d\n,POP data is %d\n",depth,val); clearLinkedStack(&S); traverseLinkedStack(&S,&depth); printf("the LinkedListStack depth is %d\n",depth); */ return NULL; } //for nRF24l01,SPI0,ARM-LINUX void *thread5(void *str) { printf("here is thread5\n"); /* int isSendSuccess=0; unsigned char txBuf[2]={0x08,0x41}; unsigned char rxBuf[2]={0,0}; unsigned char rfTxAddr[5]={0x70,0x70,0x84,0x06,0x17}; unsigned char rfRxAddr[5]={0x70,0x70,0x84,0x06,0x17}; unsigned char startTransfer[2]={0,0}; int spi0fd=0,gpiofd=0; spi0fd = spiOpen(); if( -1 == spi0fd ) { printf("can't open spi device 0\n"); exit(-1); } else { printf("spi open successful\n"); } gpiofd = gpioOpen(); if( -1 == gpiofd ) { printf("can't open gpio 0\n"); exit(-1); } else { printf("gpio 0 open successful\n"); } if ( -1 == spiSet(spi0fd) ) { printf("can't set spi device 0\n"); exit(-1); } else { printf("spi 0 set successful\n"); } nRF24L01Init(gpiofd); rfBeginTransfer(spi0fd,0xff,startTransfer);//启动传输 printf("startTransfer[0]=%#x,startTransfer[1]=%#x\n",startTransfer[0],startTransfer[1]); if ( -1 == nRF2401SelfCheckExist(spi0fd) ) { printf("\nnRF2401SelfCheckExist():HOST'S NRF24L01 is not Exist\n"); } else { printf("\nnRF2401SelfCheckExist(): HOST'S NRF24L01 is Exist\n"); } while(1) { TX_Mode(gpiofd,spi0fd,rfTxAddr,txBuf); isSendSuccess=RF_Send_to_MSub(spi0fd); if( 1 == isSendSuccess) { RX_Mode(gpiofd,spi0fd,rfRxAddr); RF_Revc_from_MSub(spi0fd,rxBuf); } usleep(200000); } spiClose(spi0fd); gpioClose(gpiofd); */ return NULL; } void *thread6(void *str) { printf("here is thread6\n"); /* int val = 0; struct arrayQueue Q; struct arrayQueue * pQ = &Q; arrayQueueCreat(&Q,6); printf("entry the array queue!\n"); enArrayQueue(pQ,1); enArrayQueue(pQ,2); enArrayQueue(pQ,3); enArrayQueue(pQ,4); enArrayQueue(pQ,5); //enArrayQueue(pQ,3); traverseArrayQueue(pQ); printf("pQ->arrayLen = %d,pQ->queueLen = %d\n",pQ->arrayLen,pQ->queueLen); printf("out the array queue!\n"); outArrayQueue(pQ,&val); outArrayQueue(pQ,&val); outArrayQueue(pQ,&val); outArrayQueue(pQ,&val); outArrayQueue(pQ,&val); //outArrayQueue(pQ,&val); traverseArrayQueue(pQ); printf("pQ->arrayLen = %d,pQ->queueLen = %d,val = %d\n",pQ->arrayLen,pQ->queueLen,val); */ /* int len=0; int val=0; struct linkedQueue Queue; struct linkedQueue *pQueue = &Queue; linkedQueueCreat(pQueue); enLinkedQueue(pQueue,1); enLinkedQueue(pQueue,2); enLinkedQueue(pQueue,3); enLinkedQueue(pQueue,4); enLinkedQueue(pQueue,5); traverseLinkedQueue(pQueue,&len); printf("len = %d\n",len); outLinkedQueue(pQueue,&val); printf("outLinkedQueue data is = %d\n",val); traverseLinkedQueue(pQueue,&len); printf("len = %d\n",len); outLinkedQueue(pQueue,&val); printf("outLinkedQueue data is = %d\n",val); traverseLinkedQueue(pQueue,&len); printf("len = %d\n",len); enLinkedQueue(pQueue,5); traverseLinkedQueue(pQueue,&len); printf("len = %d\n",len); */ return NULL; } 关于数据结构相关可以查看文件: ArrayList.c LinkedList.c ArrayQueue.c LinkedQueue.c LinkedStack.c
相关文章推荐
- 【线段树】浅谈区间问题(2)
- 共同学习Java源代码--数据结构--ArrayList类(一)
- sdutoj 3362 数据结构实验之图论六:村村通公路(最小生成树(裸的))
- 数据结构实验之二叉树五:层序遍历
- sdutoj 3361 数据结构实验之图论四:迷宫探索(dfs)
- 数据结构--深入数组
- 数据结构与算法练习-回溯、递归
- 关于 两个栈实现队列的方法
- redis数据结构指南:sorted set
- redis数据结构指南:set
- redis数据结构指南:hash
- redis数据结构指南:list
- redis数据结构指南:开篇
- Redis数据结构指南:string
- 【数据结构】位图BitMap与布隆过滤器BloomFilter
- 【数据结构】位图BitMap与布隆过滤器BloomFilter
- python set(集合)数据结构
- 数据结构上机测试1:顺序表的应用
- libiop网络库数据结构和基础知识
- Hive 中的复合数据结构简介以及一些函数的用法说明