Linux嵌入式学习——数据结构——队列

一、概念

1)定义 

是只允许在一端进行插入操作,而在另一端进行删除操作的线性表
队列 是一种 先进先出(First In First Out) 的线性表
 
线性表有顺序存储和链式存储,栈是线性表,所以有这两种存储方式
同样,队列作为一种特殊的线性表,也同样存在这两种存储方式
(2)队头

允许删除的一端称为对头
(3)队尾

允许插入的一端称为队尾

二、循环队列

当然,以下是对您提供的函数接口的基本介绍,不包括具体的实现代码:

1. SeqQueue *CreateSeqQueue(int len);

功能
此函数用于创建一个新的顺序队列(SeqQueue),并初始化其容量为len。它分配必要的内存来存储队列的元素,并设置队列的初始状态(如头尾指针、容量等)。

参数

  • int len:指定队列的初始容量,即队列可以存储的最大元素数量。

返回值

  • 返回一个指向新创建的顺序队列的指针。如果内存分配失败,则返回NULL。

SeqQueue *CreateSeqQueue(int len)
{SeqQueue * sq = malloc(sizeof(SeqQueue));if(NULL == sq){perror("CreateSeqQueue");return NULL;}sq->array  = malloc(sizeof(DATATYPE)*len);if(NULL == sq->array){perror("CreateSeqQueue");return NULL;}sq->head = 0;sq->tail = 0 ;sq->tlen = len;return sq;
}

2. int QuitSeqQueue(SeqQueue *queue);

注意:是从队列中移除并返回头部元素的操作(类似于出队)。

功能
从顺序队列的头部移除一个元素,但此函数的返回值通常应该是被移除的元素的值或操作的状态码(成功/失败)。如果直接返回元素值,可能需要额外的参数来传递该值(如使用指针参数)。

参数

  • SeqQueue *queue:指向要操作的顺序队列的指针。

返回值

  • 如果队列为空,则返回某种错误码(如-1)。如果队列不为空,根据实现,可能返回被移除的元素的值(但通常这种实现会需要一个额外的参数来接收值),或者一个表示成功的状态码(如0或1)。
  • int QuitSeqQueue(SeqQueue *queue)
    {if(IsEmptySeqQueue(queue)){fprintf(stderr,"QuitSeqQueue error\n");return 1;}queue->head= (queue->head +1)%queue->tlen;return 0;
    }
    

3. int EnterSeqQueue(SeqQueue *queue, DATATYPE *data);

功能
将一个元素添加到顺序队列的尾部。

参数

  • SeqQueue *queue:指向要操作的顺序队列的指针。
  • DATATYPE *data:指向要添加到队列中的元素的指针。但请注意,更常见的做法是直接传递元素的值(即DATATYPE data),而不是指针。

返回值

  • 如果成功添加元素,则返回1或表示成功的状态码。如果队列已满,则返回0或表示失败的状态码
int EnterSeqQueue(SeqQueue *queue, DATATYPE *data)
{if(IsFullSeqQueue(queue)){fprintf(stderr,"EnterSeqQueue error\n");return 1;}memcpy(&queue->array[queue->tail],data,sizeof(DATATYPE));queue->tail = (queue->tail+1)%queue->tlen;return 0;}

4. int IsEmptySeqQueue(SeqQueue *queue);

功能
检查顺序队列是否为空。

参数

  • SeqQueue *queue:指向要检查的顺序队列的指针。

返回值

  • 如果队列为空,则返回1(或非0值,具体取决于设计)。如果队列不为空,则返回0。
int IsEmptySeqQueue(SeqQueue *queue)
{return queue->head == queue->tail;
}

5. int IsFullSeqQueue(SeqQueue *queue);

功能
检查顺序队列是否已满。

参数

  • SeqQueue *queue:指向要检查的顺序队列的指针。

返回值

  • 如果队列已满,则返回1(或非0值,具体取决于设计)。如果队列未满,则返回0。
  • int IsFullSeqQueue(SeqQueue *queue)
    {return queue->head == (queue->tail+1) %queue->tlen;
    }
    

    空队列和满队列按理说条件是一样的,发明者为了区别开,将满队列的条件 判断tail+1与head相同则满。

6. int DestroySeqQueue(SeqQueue *queue);

功能
销毁顺序队列,释放其占用的所有内存资源。

参数

  • SeqQueue *queue:指向要销毁的顺序队列的指针。

返回值

  • 如果成功销毁队列,则返回1或表示成功的状态码。如果发生错误(尽管在销毁操作中很少出现),则返回0或表示失败的状态码。但在实践中,此函数通常不返回任何值(即返回类型为void)。
  • 
    int DestroySeqQueue(SeqQueue *queue)
    {free(queue->array);free(queue);return 0;
    }

7. DATATYPE* GetHeadSeqQueue(SeqQueue *queue);

功能
获取顺序队列头部的元素,但不从队列中移除它。

参数

  • SeqQueue *queue:指向要操作的顺序队列的指针。

返回值

  • 返回一个指向队列头部元素的指针。如果队列为空,则返回NULL或某种表示空队列的指针(尽管更常见的做法是返回NULL,并让调用者检查是否为空)。
DATATYPE *GetHeadSeqQueue(SeqQueue *queue)
{if(IsEmptySeqQueue(queue)){return NULL;}return &queue->array[queue->head];
}

 练习:

两个线程。一个分配任务,一个执行任务。
分配任务得线程入队,执行线程,出队执行任务。任务使用队列保存。如果任务内容是over,分配任务线程,等待执行线程一起结束。执行线程执行到over任务,线程结束。

.h

#ifndef SEQQUEUE_H
#define SEQQUEUE_H//#define error_exit(_errmsg_)	error(EXIT_FAILURE, errno, _errmsg_)
typedef struct
{char task_name[50];int task_time;
}
DATATYPE;
typedef struct queue {DATATYPE *array;int tlen;int head;int tail;
}SeqQueue;
SeqQueue *CreateSeqQueue(int len);
int  QuitSeqQueue(SeqQueue *queue);
int EnterSeqQueue(SeqQueue *queue, DATATYPE *data);
int IsEmptySeqQueue(SeqQueue *queue);
int IsFullSeqQueue(SeqQueue *queue);
int DestroySeqQueue(SeqQueue *queue);
DATATYPE* GetHeadSeqQueue(SeqQueue *queue);
#endif // SEQQUEUE_H

.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include "seqqueue.h"SeqQueue *CreateSeqQueue(int len)
{SeqQueue * sq = malloc(sizeof(SeqQueue));if(NULL == sq){perror("CreateSeqQueue");return NULL;}sq->array  = malloc(sizeof(DATATYPE)*len);if(NULL == sq->array){perror("CreateSeqQueue");return NULL;}sq->head = 0;sq->tail = 0 ;sq->tlen = len;return sq;
}int EnterSeqQueue(SeqQueue *queue, DATATYPE *data)
{if(IsFullSeqQueue(queue)){fprintf(stderr,"EnterSeqQueue error\n");return 1;}memcpy(&queue->array[queue->tail],data,sizeof(DATATYPE));queue->tail = (queue->tail+1)%queue->tlen;return 0;}int IsEmptySeqQueue(SeqQueue *queue)
{return queue->head == queue->tail;
}int IsFullSeqQueue(SeqQueue *queue)
{return queue->head == (queue->tail+1) %queue->tlen;
}int QuitSeqQueue(SeqQueue *queue)
{if(IsEmptySeqQueue(queue)){fprintf(stderr,"QuitSeqQueue error\n");return 1;}queue->head= (queue->head +1)%queue->tlen;return 0;
}DATATYPE *GetHeadSeqQueue(SeqQueue *queue)
{if(IsEmptySeqQueue(queue)){return NULL;}return &queue->array[queue->head];
}int DestroySeqQueue(SeqQueue *queue)
{free(queue->array);free(queue);return 0;
}

main.c

#include <stdio.h>
#include "seqqueue.h"
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>sem_t sem_task;
typedef struct
{int id;char task_name[50];int task_time;
}TASK;TASK task[]={{0,"washing",5},{1,"cooking",9},{2,"working",3},{3,"over",0},};
void* th(void* arg)
{SeqQueue* sq = (SeqQueue* )arg;DATATYPE * tmp=NULL;while(1){sem_wait(&sem_task);tmp = GetHeadSeqQueue(sq);if(0==strcmp("over",tmp->task_name)){break;}while(tmp->task_time--){printf("i'm %s\n",tmp->task_name);sleep(1);}QuitSeqQueue(sq);}return NULL;
}
int main()
{pthread_t tid;sem_init(&sem_task,0,0);SeqQueue* sq = CreateSeqQueue(10);pthread_create(&tid,NULL,th,sq);int i= 0 ;for(i = 0 ;i<4;i++){printf("id:%d name:%s time:%d\n",task[i].id,task[i].task_name,task[i].task_time);}DATATYPE data;int end_flag = 1;while(end_flag){bzero(&data,sizeof(data));int num = -1 ;char buf[5]={0};fgets(buf,sizeof(buf),stdin);num = atoi(buf);switch (num) {case 0:strcpy(data.task_name,task[0].task_name);data.task_time = task[0].task_time;EnterSeqQueue(sq,&data);break;case 1:strcpy(data.task_name,task[1].task_name);data.task_time = task[1].task_time;EnterSeqQueue(sq,&data);break;case 2:strcpy(data.task_name,task[2].task_name);data.task_time = task[2].task_time;EnterSeqQueue(sq,&data);break;case 3: //overstrcpy(data.task_name,task[3].task_name);data.task_time = task[3].task_time;EnterSeqQueue(sq,&data);end_flag=0;break;default://overstrcpy(data.task_name,task[3].task_name);data.task_time = task[3].task_time;EnterSeqQueue(sq,&data);end_flag=0;break;}sem_post(&sem_task);}pthread_join(tid,NULL);sem_destroy(&sem_task);DestroySeqQueue(sq);printf("Hello World!\n");return 0;
}

三、链式队列

链表队列(Linked List Queue)是一种使用链表数据结构实现的队列。队列是一种先进先出(FIFO, First In First Out)的数据结构,它允许在队列的一端(通常是队尾)添加元素,在另一端(通常是队首)移除元素。链表队列通过链表节点来存储队列中的元素,每个节点包含数据部分和指向列表中下一个节点的指针(或引用)

1. LinkQueue *CreateLinkQueue();

功能描述:创建一个空的链式队列。

实现思路

  • 分配内存给LinkQueue类型的指针。
  • 初始化队列的头部和尾部指针为NULL,表示队列为空。
  • 初始化队列的其他可能属性(如队列长度等)。
  • 返回指向新创建的队列的指针。
LinkQueue *CreateLinkQueue()
{LinkQueue* lq =(LinkQueue*)malloc(sizeof(LinkQueue));if(NULL == lq){perror("CreateLinkQueue malloc");return NULL;}lq->head =NULL;lq->tail =NULL;lq->clen = 0 ;return lq;}

2. int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);

功能描述:向链式队列中插入一个新的元素。

实现思路

  • 创建一个新的节点,将data指针所指向的值复制到新节点的数据域中。
  • 如果队列为空(头部和尾部指针均为NULL),则新节点既是头节点也是尾节点。
  • 如果队列不为空,将新节点插入到尾部,并更新尾部指针指向新节点。
  • 更新队列长度(如果维护了队列长度的话)。
  • 返回成功或失败的状态码。
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data)
{QueueNode*newnode = (QueueNode*)malloc(sizeof(QueueNode));if(NULL == newnode){perror("EnterLinkQueue malloc");return 1;}memcpy(&newnode->data,data,sizeof(DATATYPE));newnode->next = NULL;if(IsEmptyLinkQueue(queue)){queue->head = newnode;queue->tail = newnode;}else{queue->tail->next = newnode;queue->tail = newnode;}queue->clen++;return 0;}

3. int QuitLinkQueue(LinkQueue *queue);

功能描述:从链式队列中删除队首元素。

实现思路

  • 如果队列为空,则直接返回失败或错误码。
  • 否则,获取队首节点的指针,并将其从队列中移除(即更新头部指针)。
  • 释放原队首节点的内存。
  • 如果移除后队列为空,更新尾部指针为NULL
  • 更新队列长度(如果维护了队列长度的话)。
  • 返回成功或失败的状态码。
int QuitLinkQueue(LinkQueue *queue)
{if(IsEmptyLinkQueue(queue)){return 1;}QueueNode* tmp = queue->head;queue->head = queue->head->next;if(NULL ==queue->head){queue->tail = NULL;}free(tmp);queue->clen--;return 0;
}

4. int IsEmptyLinkQueue(LinkQueue *queue);

功能描述:检查链式队列是否为空。

实现思路

  • 如果队列的头部指针为NULL,则队列为空,返回真(或特定值表示空)。
  • 否则,队列不为空,返回假(或特定值表示非空)。
int IsEmptyLinkQueue(LinkQueue *queue)
{return 0 == queue->clen;
}

5. int DestroyLinkQueue(LinkQueue *queue);

功能描述:销毁链式队列,释放其占用的所有内存。

实现思路

  • 遍历队列,释放每个节点的内存。
  • 将队列的头部和尾部指针置为NULL
  • 如果需要,可以释放LinkQueue结构体本身占用的内存(如果它是动态分配的)。
  • 返回成功或失败的状态码。
int DestroyLinkQueue(LinkQueue *queue)
{int i =0 ;int len = GetSizeLinkQueue(queue);for(i=0;i<len;i++){QuitLinkQueue(queue);}free(queue);return 0;}

6. DATATYPE * GetHeadLinkQueue(LinkQueue *queue);

功能描述:获取链式队列的队首元素(但不删除它)。

实现思路

  • 如果队列为空,则返回NULL或特定值表示队列为空。
  • 否则,返回队首节点的数据指针。
DATATYPE *GetHeadLinkQueue(LinkQueue *queue)
{if(IsEmptyLinkQueue(queue)){return NULL;}return &queue->head->data;
}

7. int GetSizeLinkQueue(LinkQueue *queue);

功能描述:获取链式队列的元素个数。

实现思路

  • 如果队列结构体中直接维护了队列长度,则直接返回该值。
  • 否则,需要遍历队列来统计元素个数,并返回。

这些函数共同构成了链式队列的基本操作集,是链表实现队列数据结构时常见的功能。

int GetSizeLinkQueue(LinkQueue *queue)
{return queue->clen;
}

总体;

.h

#ifndef LINKQUEUE_H
#define LINKQUEUE_H#ifndef __HEAD_H__
#define __HEAD_H__
typedef int DATATYPE;typedef struct node {DATATYPE data;struct node *next;
}QueueNode;typedef struct queue {QueueNode *head;int clen;QueueNode *tail;
}LinkQueue;
LinkQueue *CreateLinkQueue();
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);
int QuitLinkQueue(LinkQueue *queue);
int IsEmptyLinkQueue(LinkQueue *queue);
int DestroyLinkQueue(LinkQueue *queue);
DATATYPE * GetHeadLinkQueue(LinkQueue *queue);
int GetSizeLinkQueue(LinkQueue *queue);
#endif
#endif // LINKQUEUE_H

.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include "linkqueue.h"
LinkQueue *CreateLinkQueue()
{LinkQueue* lq =(LinkQueue*)malloc(sizeof(LinkQueue));if(NULL == lq){perror("CreateLinkQueue malloc");return NULL;}lq->head =NULL;lq->tail =NULL;lq->clen = 0 ;return lq;}int EnterLinkQueue(LinkQueue *queue, DATATYPE *data)
{QueueNode*newnode = (QueueNode*)malloc(sizeof(QueueNode));if(NULL == newnode){perror("EnterLinkQueue malloc");return 1;}memcpy(&newnode->data,data,sizeof(DATATYPE));newnode->next = NULL;if(IsEmptyLinkQueue(queue)){queue->head = newnode;queue->tail = newnode;}else{queue->tail->next = newnode;queue->tail = newnode;}queue->clen++;return 0;}int IsEmptyLinkQueue(LinkQueue *queue)
{return 0 == queue->clen;
}int QuitLinkQueue(LinkQueue *queue)
{if(IsEmptyLinkQueue(queue)){return 1;}QueueNode* tmp = queue->head;queue->head = queue->head->next;if(NULL ==queue->head){queue->tail = NULL;}free(tmp);queue->clen--;return 0;
}DATATYPE *GetHeadLinkQueue(LinkQueue *queue)
{if(IsEmptyLinkQueue(queue)){return NULL;}return &queue->head->data;
}int GetSizeLinkQueue(LinkQueue *queue)
{return queue->clen;
}int DestroyLinkQueue(LinkQueue *queue)
{int i =0 ;int len = GetSizeLinkQueue(queue);for(i=0;i<len;i++){QuitLinkQueue(queue);}free(queue);return 0;}

main.c

#include <stdio.h>
#include "linkqueue.h"
int main()
{LinkQueue* lq = CreateLinkQueue();int i = 0 ;for(i=0;i<10;i++){EnterLinkQueue(lq,&i);}int size = GetSizeLinkQueue(lq);for(i=0;i<size;i++){DATATYPE* tmp = GetHeadLinkQueue(lq);printf("%d\n",*tmp);QuitLinkQueue(lq);}DestroyLinkQueue(lq);return 0;
}

练习:

找出目录中的.h 文件里的#define

把某个指定目录下面所有 .h
#define
1.主线程
目录 ,入队
文件 .h
找#define
写文件 log
#define 。。。。。 24 xxxx.h
2.工作线程
阻塞,出队,递归目录
目录 ,递归
文件 .h
写文件 log
#define 。。。。。 24 xxxx.h

准备工作:

#include <stdio.h>  
#include <dirent.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <string.h>  // 处理单个文件,搜索#define行并写入日志  
int do_handle_file(char *newpath, FILE *dst) {  FILE *fp = fopen(newpath, "r"); // 打开文件以读取  if (NULL == fp) {  perror("do_handle_file fopen"); // 如果打开文件失败,打印错误信息  fprintf(stderr, "filename %s\n", newpath); // 打印出错的文件名  return 1; // 返回错误码  }  int num = 1; // 行号计数器,从1开始  while (1) {  char buf[1024] = {0}; // 读取缓冲区  if (NULL == fgets(buf, sizeof(buf), fp)) {  break; // 如果到达文件末尾或读取错误,跳出循环  }  if (strstr(buf, "#define")) { // 如果行中包含#define  buf[strlen(buf) - 1] = '\0'; // 去除行尾的换行符  fprintf(dst, "%s %d %s\n", buf, num, newpath); // 将处理后的行写入目标文件,包括行号和文件名  fflush(dst); // 刷新输出缓冲区,确保数据立即写入文件  }  num++; // 行号递增  }  fclose(fp); // 关闭文件  // 注意:这里缺少了返回语句,但按照函数逻辑,应该返回0表示成功  return 0; // 假设补充的返回语句  
}  // 递归遍历目录,处理所有.h文件  
void do_ls(char *pathname, FILE *fp) {  DIR *dir = opendir(pathname); // 打开目录  if (NULL == dir) {  perror("opendir"); // 如果打开目录失败,打印错误信息  fprintf(stderr, "pathname %s\n", pathname); // 打印出错的目录名  return; // 提前返回  }  struct dirent *info; // 读取目录项的结构体指针  char newpath[512] = {0}; // 构造新路径的缓冲区  while ((info = readdir(dir)) != NULL) { // 遍历目录项  sprintf(newpath, "%s/%s", pathname, info->d_name); // 构造完整路径  printf("processing %s\n", newpath); // 打印正在处理的文件或目录  // 注意:这里应该使用stat函数来检查文件类型,因为d_type可能不是所有系统都支持  // 但是为了保持代码的一致性,我们假设d_type是可用的  if (DT_DIR == info->d_type) { // 如果是目录  if (strcmp(info->d_name, ".") == 0 || strcmp(info->d_name, "..") == 0) {  continue; // 跳过当前目录和上级目录  }  do_ls(newpath, fp); // 递归处理子目录  } else { // 假设不是目录,则检查是否为.h文件  if (strlen(info->d_name) < 3) {  continue; // 文件名长度不足,不可能是.h文件  }  // 注意:字符串比较的方式有误,应该是从末尾开始比较".h"  if (strcmp(".h", &info->d_name[strlen(info->d_name) - 2]) == 0) {  do_handle_file(newpath, fp); // 处理该文件  }  // else { continue; } // 这一行是多余的,因为已经在if-else之外了  }  }  closedir(dir); // 关闭目录  
}  int main(int argc, char *argv[]) {  FILE *fp = fopen("log", "w"); // 打开日志文件以写入  if (NULL == fp) {  perror("fopen"); // 如果打开文件失败,打印错误信息  return 1; // 返回错误码  }  do_ls("/home/linux", fp); // 遍历/home/linux目录及其子目录  fclose

.h

#ifndef LINKQUEUE_H
#define LINKQUEUE_H#ifndef __HEAD_H__
#define __HEAD_H__
typedef struct
{char path[512];}DATATYPE;typedef struct node {DATATYPE data;struct node *next;
}QueueNode;typedef struct queue {QueueNode *head;int clen;QueueNode *tail;
}LinkQueue;
LinkQueue *CreateLinkQueue();
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);
int QuitLinkQueue(LinkQueue *queue);
int IsEmptyLinkQueue(LinkQueue *queue);
int DestroyLinkQueue(LinkQueue *queue);
DATATYPE * GetHeadLinkQueue(LinkQueue *queue);
int GetSizeLinkQueue(LinkQueue *queue);
#endif
#endif // LINKQUEUE_H

.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include "linkqueue.h"
LinkQueue *CreateLinkQueue()
{LinkQueue* lq =(LinkQueue*)malloc(sizeof(LinkQueue));if(NULL == lq){perror("CreateLinkQueue malloc");return NULL;}lq->head =NULL;lq->tail =NULL;lq->clen = 0 ;return lq;}int EnterLinkQueue(LinkQueue *queue, DATATYPE *data)
{QueueNode*newnode = (QueueNode*)malloc(sizeof(QueueNode));if(NULL == newnode){perror("EnterLinkQueue malloc");return 1;}memcpy(&newnode->data,data,sizeof(DATATYPE));newnode->next = NULL;if(IsEmptyLinkQueue(queue)){queue->head = newnode;queue->tail = newnode;}else{queue->tail->next = newnode;queue->tail = newnode;}queue->clen++;return 0;}int IsEmptyLinkQueue(LinkQueue *queue)
{return 0 == queue->clen;
}int QuitLinkQueue(LinkQueue *queue)
{if(IsEmptyLinkQueue(queue)){return 1;}QueueNode* tmp = queue->head;queue->head = queue->head->next;if(NULL ==queue->head){queue->tail = NULL;}free(tmp);queue->clen--;return 0;
}DATATYPE *GetHeadLinkQueue(LinkQueue *queue)
{if(IsEmptyLinkQueue(queue)){return NULL;}return &queue->head->data;
}int GetSizeLinkQueue(LinkQueue *queue)
{return queue->clen;
}int DestroyLinkQueue(LinkQueue *queue)
{int i =0 ;int len = GetSizeLinkQueue(queue);for(i=0;i<len;i++){QuitLinkQueue(queue);}free(queue);return 0;}

main.c

#include <stdio.h>
#include "linkqueue.h"
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <dirent.h>
sem_t sem_task;
pthread_mutex_t mutex;
pthread_t main_th;
int  do_handle_file(char * newpath,FILE* dst)
{FILE*fp  =fopen(newpath,"r");if(NULL == fp){perror(" do_handle_file  fopen");fprintf(stderr,"filename %s\n",newpath);return 1;}int num =1;while(1){char buf[1024]={0};if(NULL == fgets(buf,sizeof(buf),fp)){break;}if(strstr(buf,"#define")){buf[strlen(buf)-1]='\0';fprintf(dst,"%s %d %s\n",buf,num,newpath);fflush(dst);}num++;}fclose(fp);return 0;
}void do_ls(char *pathname,FILE* fp,LinkQueue* lq)
{DIR* dir = opendir(pathname);// home/linuxif(NULL == dir){perror("opendir");fprintf(stderr,"pathname %s\n",pathname);return ;}DATATYPE data;while(1){bzero(&data,sizeof(data));struct dirent * info = readdir(dir);if(NULL == info){break;}char newpath[512]={0};sprintf(newpath,"%s/%s",pathname,info->d_name);printf("processing %s\n",newpath);if(DT_DIR == info->d_type){if(0 == strcmp(info->d_name,".")|| 0 == strcmp(info->d_name,"..")){continue;}if(pthread_self() == main_th)// this th is main_th{strcpy(data.path,newpath);pthread_mutex_lock(&mutex);EnterLinkQueue(lq,&data);pthread_mutex_unlock(&mutex);sem_post(&sem_task);}else{do_ls(newpath,fp,lq);// 1   /home/linux/1}}else{if(strlen(info->d_name)<3){continue;}if(0==strcmp(".h",&info->d_name[strlen(info->d_name)-2])){do_handle_file(newpath,fp);}else{continue;}}}closedir(dir);
}
typedef struct
{FILE* fp ;LinkQueue* lq;
}TH_ARG;
void * th(void* arg)
{TH_ARG* th_arg = (TH_ARG*)arg;FILE*fp = th_arg->fp;LinkQueue* lq = th_arg->lq;DATATYPE data;while(1){bzero(&data,sizeof(data));sem_wait(&sem_task);pthread_mutex_lock(&mutex);DATATYPE*tmp = GetHeadLinkQueue(lq);memcpy(data.path,tmp->path,sizeof(data.path));QuitLinkQueue(lq);pthread_mutex_unlock(&mutex);if(0==strcmp(data.path,"over")){break;}do_ls(data.path,fp,lq);}return NULL;
}
int main()
{main_th= pthread_self();pthread_t tid[3]={0};LinkQueue* lq = CreateLinkQueue();FILE* fp = fopen("log","w");if(NULL==fp){perror("fopen");return 1;}TH_ARG arg={0};arg.fp = fp;arg.lq = lq;sem_init(&sem_task,0,0);pthread_mutex_init(&mutex,NULL);int i = 0 ;for(i=0;i<3;i++){pthread_create(&tid[i],NULL,th,&arg);}do_ls("/home/linux",fp,lq);DATATYPE data;for(i=0;i<3;i++){bzero(&data,sizeof(data));strcpy(data.path,"over");EnterLinkQueue(lq,&data);sem_post(&sem_task);}for(i=0;i<3;i++){pthread_join(tid[i],NULL);}pthread_mutex_destroy(&mutex);sem_destroy(&sem_task);DestroyLinkQueue(lq);fclose(fp);printf("aaaaaaaaaaaa\n");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/49781.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【在开发小程序的时候如何排查问题】

在开发小程序的时候如何排查问题 在最近开发小程序的时候&#xff0c;经常出现本地在浏览器中调试没有问题&#xff0c;但是一发布到预发环境就出现各种个样的问题 手机兼用性问题 有时候会出现苹果&#x1f34e;手机键盘弹出&#xff0c;导致ui界面高度出现异常边界问题&#…

Arduino IDE界面和设置(基础知识)

Arduino IDE界面和设置&#xff08;基础知识&#xff09; 1-2 Arduino IDE界面和设置如何来正确选择Arduino开发板型号如何正确选择Arduino这个端口如何来保存一个Arduino程序Arduino ide 的界面功能按钮验证编译上传新建打开保存工作状态 1-2 Arduino IDE界面和设置 大家好这…

如何穿透模糊,还原图片真实面貌

目录 图像清晰化的魔法棒&#xff1a;AI如何穿透模糊&#xff0c;还原图片真实面貌 前言 论文背景 论文思路 模型介绍 复现过程 演示视频 使用方式 本文所涉及所有资源均在传知代码平台可获取。 图像清晰化的魔法棒&#xff1a;AI如何穿透模糊&#xff0c;还原图片真实面貌 在我…

全网最最实用--模型高效推理:量化基础

文章目录 一、量化基础--计算机中数的表示1. 原码&#xff08;Sign-Magnitude&#xff09;2. 反码&#xff08;Ones Complement&#xff09;3. 补码&#xff08;Twos Complement&#xff09;4. 浮点数&#xff08;Floating Point&#xff09;a.常用的浮点数标准--IEEE 754(FP32…

状态机 XState 使用

状态机 一般指的是有限状态机&#xff08;Finite State Machine&#xff0c;FSM&#xff09;&#xff0c;又可以称为有限状态自动机&#xff08;Finite State Automation&#xff0c;FSA&#xff09;&#xff0c;简称状态机&#xff0c;它是一个数学模型&#xff0c;表示有限个…

【计算机网络】数据链路层实验

一&#xff1a;实验目的 1&#xff1a;学习WireShark软件的抓包操作&#xff0c;分析捕获的以太网的MAC帧结构。 2&#xff1a;学习网络中交换机互相连接、交换机连接计算机的拓扑结构&#xff0c;理解虚拟局域网&#xff08;WLAN&#xff09;的通信机制。 3&#xff1a;学习…

cas 和 synchronized 优化过程

cas 什么是CAS CAS:全称Compareandswap&#xff0c;字⾯意思:”⽐较并交换“&#xff0c;⼀个CAS涉及到以下操作&#xff1a; 我们假设内存中的原数据V&#xff0c;旧的预期值A&#xff0c;需要修改的新值B。 1. ⽐较A与V是否相等。&#xff08;⽐较&#xff09; 2. 如果⽐较…

ubuntu22.04单个网口两个IP

其中 4网段IP可用来上网&#xff0c;3 网段用来内网 界面显示: 配置文件&#xff1a; 01-network-manager-all.yaml 放在 /etc/netplan/ # Let NetworkManager manage all devices on this systemnetwork:version: 2renderer: networkdethernets:eth0:dhcp4: falsedhcp6: …

开放式耳机哪个牌子好?五大超值机型整理,速速收藏!!

大家都知道现在的开放式耳机是越来越火了&#xff0c;后台也有非常多的小伙伴来私信&#xff0c;作为一个耳机测评师&#xff0c;当然是为了你们服务啦&#xff0c;所以这一期文章&#xff0c;就是为了个大家答疑解惑&#xff0c;告诉大家如何才能选购出一款比较好用的开放式耳…

万字长文详解Java反射技术 | JavaSE | Java进阶知识 | 源码

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 &#x1f4cc;今天分享的是JavaSE中的进阶知识&#x1f6d1;&#xff1a;反射技术。内容有点长&#xff0c;非常全面&#xff0c;记得点赞&#x1f44d;、收藏✅加关…

【网络世界】HTTP协议

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 概念 &#x1f4c1; URL &#x1f4c2; urlencode 和 urldecode &#x1f4c1; 协议格式 &#x1f4c1; 方法 &#x1f4c2; GET/get &#x1f4c2; POST/post &#x1f4c1; 常见的报头 &#x1f4c1; 状态码 &…

模型大小的指标和模型量化的指标和手段

一、模型大小的指标 1.计算量 计算次数&#xff0c;反映了模型对硬件计算单元的需求。计算量的单位是 OPs(Operations) 。最常用的数据格式 为 float32&#xff0c;因此float32类型下的计算量单位被写作 FLOPs (Floating Point Operations)&#xff0c;即浮点计算次数。模型的…

3D Web轻量化引擎HOOPS Communicator针对复杂大模型Web端可视化的解决方案

随着工程设计、制造和建筑领域中三维模型的日益复杂化&#xff0c;如何在Web端高效处理和展示这些大规模数据成为一大挑战。HOOPS Communicator作为一款强大的3D可视化工具&#xff0c;提供了一套针对复杂大模型的轻量化解决方案&#xff0c;涵盖了模型轻量化及格式转换、超大模…

PostgreSQL成为最受欢迎的数据库; TiDB马拉松大赛开启, Serverless和Vector为比赛焦点

重要更新 1. TiDB Hackathon大赛报名开启&#xff0c;总奖金达21万&#xff0c;主题是基于 TiDB Serverless 内置的向量搜索功能&#xff08;Vector Search&#xff09;构建 AI 创新应用&#xff0c;感兴趣的可以报名参加。( [1] ) 2. Stack Overflow 2024 开发者调研结果公布…

自学JavaScript(放假在家自学第一天)

目录 JavaScript介绍分为以下几点 1.1 JavaScript 是什么 1.2JavaScript书写位置 1.3 Javascript注释 1.4 Javascript结束符 1.5 Javascript输入输出语法 JavaScript(是什么?) 是一种运行在客户端(浏览器)的编程语言&#xff0c;实现人机交互效果。 2.作用(做什么?)网…

从头开始微调Llama 3.1模型

在今天的科技专栏中&#xff0c;我们将深入探讨如何微调Llama 3.1模型&#xff0c;以使其更好地适应您的特定领域数据。微调大型语言模型&#xff08;如Llama&#xff09;的主要目的是为了在特定领域的数据上表现更好&#xff0c;从而生成更符合您需求的输出。以下是我们将要介…

SpringBoot知识笔记

一、基本概念 1.1 特性 起步依赖 自动配置 其它特性:内嵌的Tomcat、Jetty(无需部署WAR文件),外部配置,不需要XML配置(properties/yml)。 1.2 配置文件 SpringBoot提供了多种属性配置方式 //application.properties server.port=9090 server.servlet.context-path…

Python爬虫知识体系-----Urllib库的使用

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新&#xff1a;https://blog.csdn.net/grd_java/article/details/140574349 文章目录 1. 基本使用2. 请求对象的定制3. 编解码1. get请求方式&#xff1a;urllib.parse.quote&#xff08;&#xff09;2. ur…

邦布带你从零开始实现图书管理系统(java版)

今天我们来从零开始实现图书管理系统。 图书管理系统 来看我们的具体的实现&#xff0c;上述视频。 我们首先来实现框架&#xff0c;我们要实现图书管理系统&#xff0c;首先要搭框架。 我们首先定义一个书包&#xff0c;在书包中定义一个书类和一个书架类&#xff0c;再定义…

用Java手写jvm之实现查找class

写在前面 完成类加载器加载class的三阶段&#xff0c;加载&#xff0c;解析&#xff0c;初始化中的加载&#x1f600;&#x1f600;&#x1f600; 源码 。 jvm想要运行class&#xff0c;是根据类全限定名称来从特定的位置基于类加载器来查找的&#xff0c;分别如下&#xff1a;…