Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C/多线程/分段错误/(可能是)线程队列问题_C_Multithreading_Segmentation Fault_Coredump_Ucontext - Fatal编程技术网

C/多线程/分段错误/(可能是)线程队列问题

C/多线程/分段错误/(可能是)线程队列问题,c,multithreading,segmentation-fault,coredump,ucontext,C,Multithreading,Segmentation Fault,Coredump,Ucontext,我正在尝试创建线程库。为此,我正在尝试实现队列来存储要执行的挂起线程 #include <ucontext.h> #include <stdio.h> #include <stdlib.h> typedef struct { ucontext_t context; }MyThread; #define MAX 20 MyThread queue[MAX]; int rear=0,front=0;

我正在尝试创建线程库。为此,我正在尝试实现队列来存储要执行的挂起线程

   #include <ucontext.h>
   #include <stdio.h>
   #include <stdlib.h>

   typedef struct {
       ucontext_t context;
   }MyThread;

   #define MAX 20
   MyThread queue[MAX];
   int rear=0,front=0;

   void addToQueue(MyThread t)
   {
       if(rear==MAX)
       {
           printf("Queue is full!");
           return;
       }        
       queue[front]=t;
       front+=1;
   }

   MyThread* removeFromQueue()
   {       
       if(front==rear)
       return NULL;        
       rear=rear+1;
       return &(queue[rear-1]);       
   }

   MyThread umain;

   void MyThreadInit (void(*start_funct)(void *), void *args)
   {
    getcontext(&(umain.context));
    char p[64000];
       umain.context.uc_stack.ss_sp =(char *)p;
       umain.context.uc_stack.ss_size = sizeof(p);
       umain.context.uc_link =NULL;
       makecontext(&umain.context,(void(*)(void))start_funct,1,args);
       setcontext(&(umain.context));

   }

    MyThread MyThreadCreate (void(*start_funct)(void *), void *arg)
   {
         MyThread newthread;
       char args[10000];
        getcontext(&(newthread.context));
        newthread.context.uc_stack.ss_sp =(char *)args;
        newthread.context.uc_stack.ss_size = sizeof(args);
        newthread.context.uc_link =NULL;
        makecontext(&newthread.context,(void(*)(void))start_funct,1,arg);
        addToQueue(newthread);

        return newthread;
    }         
    void MyThreadYield(void)
    {
        MyThread* a=removeFromQueue();
        MyThread save;
        if(a != NULL)
        {
         printf("Before yielding the context \n");

         getcontext(&(save.context));
         addToQueue(save);
         //swapcontext(&umain.context,&(a->context));
         setcontext(a);    
         printf("After the swapping the context \n");
        }
        else
        { printf("NULL!!! \n");
        }
    }

    void func1(void *arg)
    {
     printf("func1started \n");        
     MyThreadYield();
    }

    void func2(void *arg)
    {
     printf("func2started \n");
     MyThreadYield();         
    }
    void func12(void *arg)
    {
     printf("func12started \n");
     MyThreadCreate(func1,arg);
     MyThreadCreate(func2,arg);
     MyThreadYield();

    }

    int main(void)
    {
        int i=0;
        printf("inside the main function \n");
        MyThreadInit(func12,&i);

        return 0;
    }

     Output :
     inside the main function
     func12started
     Before yielding the context
     func1started
     Before yielding the context
     func2started
     Before yielding the context
     func1started
     Before yielding the context
     Segmentation fault
#包括
#包括
#包括
类型定义结构{
ucontext\u t context;
}神话阅读;
#定义最大值20
读取队列[MAX];
int后=0,前=0;
void addToQueue(MyThread t)
{
如果(后==最大值)
{
printf(“队列已满!”);
返回;
}        
队列[前端]=t;
正面+=1;
}
MyThread*removeFromQueue()
{       
如果(前==后)
返回NULL;
后=后+1;
返回和(队列[rear-1]);
}
乌敏神话;
void MyThreadInit(void(*开始函数)(void*),void*参数)
{
getcontext(&(umain.context));
charp[64000];
umain.context.uc_stack.ss_sp=(char*)p;
umain.context.uc_stack.ss_size=sizeof(p);
umain.context.uc_link=NULL;
makecontext(&umain.context,(void(*)(void))start_funct,1,args);
setcontext(&(umain.context));
}
MyThread MyThreadCreate(void(*start_funct)(void*),void*arg)
{
神话阅读新线程;
字符args[10000];
getcontext(&(newthread.context));
newthread.context.uc_stack.ss_sp=(char*)参数;
newthread.context.uc_stack.ss_size=sizeof(args);
newthread.context.uc_link=NULL;
makecontext(&newthread.context,(void(*)(void))start_funct,1,arg);
addToQueue(newthread);
返回新线程;
}         
无效收益率(void)
{
MyThread*a=removeFromQueue();
神话阅读保存;
如果(a!=NULL)
{
printf(“在产生上下文之前\n”);
getcontext(&(save.context));
addToQueue(保存);
//swapcontext(&umain.context,&(a->context));
setcontext(a);
printf(“在交换上下文之后\n”);
}
其他的
{printf(“NULL!!!\n”);
}
}
void func1(void*arg)
{
printf(“func1started\n”);
MyThreadYield();
}
void func2(void*arg)
{
printf(“func2started\n”);
MyThreadYield();
}
无效函数12(无效*参数)
{
printf(“func12started\n”);
MyThreadCreate(func1,arg);
MyThreadCreate(func2,arg);
MyThreadYield();
}
内部主(空)
{
int i=0;
printf(“在主函数中\n”);
MyThreadInit(func12和&i);
返回0;
}
输出:
在主功能内部
功能启动
在让步于上下文之前
功能1开始
在让步于上下文之前
功能启动
在让步于上下文之前
功能1开始
在让步于上下文之前
分段故障
我之所以提到队列,是因为我尝试从“MyThreadYield”函数中删除下面的代码,它工作正常,但没有达到预期的功能。
getcontext(&(save.context));
addToQueue(保存)

首先,您的队列实现此时不是线程安全的。您的问题强烈建议在多线程环境中使用此代码。拥有一个非线程安全的队列会给你错误的结果,并且会发生奇怪的事情(比如
removeFromQueue()
将相同的东西返回到两个不同的线程,或者
addToQueue()
在同一位置插入两个项目)

除此之外,队列实现永远不会工作。您没有正确使用
前部
后部
。仔细查看插入函数:

void addToQueue(MyThread t)
{
    if (rear==MAX)
    {
        printf("Queue is full!");
        return;
    }        
    queue[front]=t;
    front+=1;
}
您检查
rear
是否为
MAX
,然后将其写入
队列[front]
并递增
front
。如果我继续向队列中添加项目,最终达到缓冲区的限制,会怎么样
rear
将始终为0,
front
将无限期增长,并且您的函数将超出
队列
的限制。这可能是导致分割错误的原因

我想您应该检查
front

void addToQueue(MyThread t)
{
    if (front == MAX)
    {
        printf("Queue is full!");
        return;
    }        
    queue[front]=t;
    front+=1;
}
removeFromQueue()
的代码表面上看起来不错,只要
queue
是一个全局数组(因为您返回的是指针,不能返回指向局部变量的指针)。但是,您必须从这个答案中得出的一个最重要的事实是,您的队列实现不会长期扩展。基于数组的队列是一个糟糕的选择。当阵列中的空间不足时,您会怎么做?如果我插入
MAX
元素,然后删除2个或3个,并尝试插入更多元素,会怎么样?您的代码将显示队列已满,因为它只允许您总共插入
MAX
元素。删除元素时,可以将队列中的每个元素向左移动,但这太疯狂了,而且效率极低。或者您可以增加
front
modulo
MAX
,允许
rear
位于
front
之前,只要您知道最多只能插入
MAX
元素。这会更好,但它会破坏
removeFromQueue()
中的逻辑,因为前面返回的指针可能会在您操作队列时指向不同的线程结构。绝对不是你想要的


一个非常非常好的方法是使用一个链表来实现这一点,在链表中,您可以保持指向头部的指针和指向尾部的指针。看看你的问题是什么?你会犯什么错误?你期待什么?您所说的不执行预期功能是什么意思?您的队列可能无法工作。你需要仔细阅读如何写出好的并行对象。即使你修复了你的内存错误,它也会给你错误的东西。我得到的错误:(已经在代码末尾的输出中提到)分段错误。我的问题是为什么