山东大学2018级操作系统实验五

gxc老师独有的“抓贼实验”
这个代码能手动抓到贼,当然最好可以再加一个程序来自动捕捉贼~

题目描述

通过c语言的多线程,开启多个消费者一个生产者,得到生产消费的输出,在输出中查找竞争条件(race condition),捕获错误现场。

实验涉及的知识点

1、线程创建pthread_create
线程创建函数包含四个变量,分别为:
1.一个线程变量名,被创建线程的标识
2.线程的属性指针,缺省为NULL即可
3.被创建线程的程序代码
4.程序代码的参数
pthread_create(&thrd1, NULL, (void *)&thread_function, (void *) &some_argument);

2、结束线程 pthread_exit
线程结束调用实例:pthread_exit(void *retval); //retval用于存放线程结束的退出状态

3、线程等待 pthread_join
pthread_create调用成功以后,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度,如果我们需要等待指定线程结束,需要使用pthread_join函数,这个函数实际上类似与多进程编程中的waitpid。 举个例子,以下假设 A 线程调用 pthread_join 试图去操作B线程,该函数将A线程阻塞,直到B线程退出,当B线程退出以后,A线程会收集B线程的返回码。 该函数包含两个参数:
pthread_t th //th是要等待结束的线程的标识
void **thread_return //指针thread_return指向的位置存放的是终止线程的返回状态。
调用实例:pthread_join(thrd1, NULL);

源代码

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 10
typedef struct
{
    int a;
} item;

item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
item nextConsumed;

item nextProduced;

int *consumer(void *arg)
{
    nextConsumed.a = 0;

    while (1)
    {
        while (in == out)
            ; /*do nothingf*/
        nextConsumed.a++;
        nextConsumed = buffer[out];
        out = (out + 1) % BUFFER_SIZE;
        /*consume the item in nextConsumed*/
        printf("consume the item in nextConsumed\n");
        printf("consume %d\n", nextConsumed.a);
    }
    return NULL;
}

int *producer(void *arg)
{
    nextProduced.a = 0;

    while (1)
    {
        /*produce an item in nextProduced*/
        while (((in + 1) % BUFFER_SIZE) == out)
            ;
        /*do nothing*/
        nextProduced.a++;
        buffer[in] = nextProduced;
        in = (in + 1) % BUFFER_SIZE;
        printf("produce an item in nextProduced\n");
        printf("produce %d\n", nextProduced.a);
    }
    return NULL;
}

int main(void)
{
    pthread_t con_thid1;
     pthread_t con_thid2;
      pthread_t con_thid3;
    pthread_t pro_thid;

    if (pthread_create(&con_thid1, NULL, (void *)consumer, NULL) != 0)
    {
        printf("consumer creation failed\n");
    }
     if (pthread_create(&con_thid2, NULL, (void *)consumer, NULL) != 0)
    {
        printf("consumer creation failed\n");
    }
     if (pthread_create(&con_thid3, NULL, (void *)consumer, NULL) != 0)
    {
        printf("consumer creation failed\n");
    }
    if (pthread_create(&pro_thid, NULL, (void *)producer, NULL) != 0)
    {
        printf("producer creation failed\n");
    }
    pthread_join(con_thid1, NULL);
    pthread_join(con_thid2, NULL);
    pthread_join(con_thid3, NULL);
    pthread_join(pro_thid, NULL);
    printf("ok\n");
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作系统实验主要涉及进程互斥问题。在多道程序设计中,多个进程可能会同时访问共享资源。如果这些进程没有进行合理的协调和同步,就会出现互斥问题。互斥问题的解决方案包括:信号量、互斥锁、条件变量等。 在本次实验中,我们可以采用信号量来解决进程互斥问题。具体步骤如下: 1. 定义共享资源:在本实验中,我们可以定义一个临界区,多个进程需要访问该临界区。 2. 定义信号量:定义一个二元信号量,初始值为 1,用于表示当前临界区是否可用。 3. 进程同步:当一个进程需要访问临界区时,它需要先使用_matrix.scale(scale); break; } } m_bone_matrixes[i][bone_id * 3 + 0] = bone_matrix; } } update(); } } private: struct Mesh { GLuint vao; GLuint vbo_vertices; GLuint vbo_normals; GLuint vbo_tex_coords; GLuint vbo_bone_weights; GLuint vbo_bone_indices; int num_vertices; }; void createBoneHierarchy(const aiNode *node, const QMatrix4x4 &parent_transform) { QMatrix4x4 transform; transform.translate(QVector3D(node->mTransformation.a4, node->mTransformation.b4, node->mTransformation.c4)); transform *= parent_transform; if (m_bone_mapping.contains(QString::fromStdString(node->mName.C_Str()))) { int bone_id = m_bone_mapping.value(QString::fromStdString(node->mName.C_Str())); m_bone_offset_matrices[bone_id] = m_global_inverse_transform.inverted() * transform * m_bone_offset_matrices[bone_id]; } for (unsigned int i = 0; i < node->mNumChildren; ++i) { createBoneHierarchy(node->mChildren[i], transform); } } QOpenGLShaderProgram m_program; QVector<Mesh> m_meshes; QHash<QString, int> m_bone_mapping; QVector<QMatrix4x4> m_bone_offset_matrices; QVector<QVector<QMatrix4x4>> m_bone_matrixes; QMatrix4x4 m_global_inverse_transform; QElapsedTimer m_timer; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); format.setVersion(3, 3); format.setProfile(QSurfaceFormat::CoreProfile); QSurfaceFormat::setDefaultFormat(format); GLWidget w; w.show(); return a.exec(); } ``` 这个示例代码中,Assimp 负责加载模型数据和骨骼动画数据,并将它们转换为 OpenGL 用的数据格式。OpenGL 用着色器程序进行渲染,其中包括了骨骼矩阵数组的 uniform 变量,用于在 GPU 中计算顶点位置。每一帧都需要更新骨骼矩阵数组,并重新绘制场景。 需要注意的是,上面的代码中只是一个简单的示例,实际应用中需要更多的优化和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值