您的位置:首页 > 理论基础 > 数据结构算法

关于多线程、安装信号、长跳转、数据结构等的例子

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

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: