操作系统头歌
操作系统头歌

操作系统头歌

Linux进程管理之一(属性获取,fork、exit的使用)

第1关:获取进程常见属性

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>

/**********************
 * pid: 当前进程ID
 * ppid: 父进程ID
***********************/
struct procIDInfo
{
	pid_t pid;
	pid_t ppid;
};

/************************
 * 返回值: 需要被打开的目录路径
*************************/
struct procIDInfo getProcInfo()
{
	struct procIDInfo ret;   //存放进程ID信息,并返回
	/********** BEGIN **********/
	ret.pid = getpid();
	ret.ppid = getppid();
	
	/********** END **********/

	return ret;
}

第2关:进程创建操作-fork

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

/************************
 * 提示: 不要在子进程或父进程中使用exit函数或者return来退出程序
*************************/
void createProcess()
{
	/********** BEGIN **********/
	pid_t pid;
    pid = fork();
    if(pid == -1) {
        //创建进程失败
        printf("创建进程失败(%s)!\n", strerror(errno));
        return -1;
    }
    else if(pid == 0) {
        //子进程
        printf("Children");
    }
    else {
        //父进程
        printf("Parent");
    }
    
	
	/********** END **********/
}

第3关:进程终止

#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>

/************************
 * 提示: 用户需要在exitProcess函数中使用atexit函数注册一个自定义函数,并在自定义函数中打印出当前进程ID号
*************************/

void printPID()
{
	printf("%d", getpid());
}


void exitProcess()
{
	/********** BEGIN **********/
	
	if (atexit(printPID) != 0){
		printf("调用atexit函数错误\n");
	}
	/********** END **********/
}

进程管理之二(wait、exec、system的使用)

第1关:进程等待

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>


/************************
 * 返回值: 调用成功且子进程正常退出返回退出代码,否则返回-1
*************************/
int waitProcess()
{
	int status = -1;
    /********** BEGIN **********/
    pid_t pid = fork(); // 创建子进程
    if (pid == -1)
    {
        perror("fork failed");
        return -1;
    }
    else if (pid == 0)
    {
        // 子进程
        sleep(2); // 模拟子进程工作
        printf("子进程执行完毕,退出代码为 42\n");
        exit(42); // 子进程退出,返回代码 42
    }
    else
    {
        // 父进程
        pid_t ret = wait(&status); // 等待子进程结束
        if (ret == -1)
        {
            perror("wait failed");
            return -1;
        }
        if (WIFEXITED(status)) // 检查子进程是否正常退出
        {
            status = WEXITSTATUS(status); // 获取子进程的退出代码
        }
        else
        {
            status = -1; // 如果子进程非正常退出,返回 -1
        }
    }
    /********** END **********/
	
	return status;
}

第2关:进程创建操作-exec函数族

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

/************************
 * 提示: 在子进程中如果执行exec函数失败要使用exit函数正确退出子进程
*************************/
int execlProcess()
{
	pid_t pid = vfork();
	if(pid == -1)
	{
		printf("创建子进程失败(%s)\n", strerror(errno));
		return -1;
	}
	else if(pid == 0)
	{
		//子进程
		/********** BEGIN **********/
		if(execlp("touch", "touch", "testFile",  NULL) < 0)
        {
            //执行execlp函数失败
            exit(-1);
        }
		
		/********** END **********/
	}
	else
	{
		//父进程
		/********** BEGIN **********/
		printf("Parent Process");
		
		/********** END **********/
	}
}

第3关:进程创建操作-system

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

/************************
 * 返回值: 调用成功返回命令的状态码,失败返回-1
*************************/
int createProcess()
{
    int ret = -1;
    /********** BEGIN **********/
    ret = system("mkdir testDir");
    if (ret == -1)
    {
        printf("创建目录失败(%s)\n", strerror(errno));
    }
    /********** END **********/
    
    return ret;
}

函数

第1关:求和

#include<stdio.h>

//编写函数
/*********Begin*********/

int sum(int n){
    int s=0;
    int i;
    for(i=1;i<=n;i++){
        s+=i;
    }
    return s;
}

/*********End**********/ 
int main(void)
{  
    /*********Begin*********/
    int x;
    scanf("%d",&x);
    printf("%d",sum(x));
    /*********End**********/ 
    return 0;
}

第2关:回文数计算

#include<stdio.h>
void solve(){
    /*********Begin*********/
    int i;
    for(i=200;i<=3000;i++){
        if(i<1000){
            if(i/100==i%10){
                printf("%d\n",i);
            }
        }else{
            if((i/1000==i%10)&&((i%100/10)==(i/100%10))){
                printf("%d\n",i);
            }
        }
    }
    /*********End**********/ 
}
int main(void)
{  
    solve();
    return 0;
}

第3关: 编写函数求表达式的值

#include<stdio.h>

double QH(int n) {
    double s = 0;
    double k = 1;
    double m = 1;

    for (int i = 1; i <= n; i++) {
        k*= i;
        m*= (2 * i + 1);
        s += k/m;
    }
    return s+1;
}

int main(void)
{
    int n;
    scanf("%d", &n);
    printf("%.10lf\n", QH(n));
    return 0;
}

第4关:阶乘数列

#include<stdio.h>
//编写函数
/*********Begin*********/

/*********End**********/ 
int main()
{
    int a,b,x;
    scanf("%d",&x);
    long long jiecheng=1, sum=0;
    for (a=1;a<=x;a++) 
    {
        for (b = 1;b <= a;b++)
        {
            jiecheng*= b;
        }
        sum+=jiecheng;
        jiecheng = 1;
    }
    printf("%lld",sum);
}

第5关:亲密数

#include <stdio.h>
int main()
{
    int a, i, b, n;
    for (a = 1; a < 3000; a++)
    {
        for (b = 0, i = 1; i <= a / 2; i++ )
        {
            if(! (a % i)) 
                b += i; 
        }
        for (n = 0, i = 1; i <= b/2; i++)
        {
            if(! (b % i)) 
                n += i;
        }
        if(n == a && a < b)
            printf("(%d,%d)", a, b); 
    }
    return 0;
}

第6关:公约公倍数


#include<stdio.h>
int main()
{
    long x, y, z, m, n;
    scanf("%ld%ld", &x, &y);
    m = x, n = y;
if(x>0&&y>0)
{
    while (y != 0)
    {
        z = x%y;
        x = y;
        y = z;
    }
    printf("%ld ", x);
    printf("%ld", m*n / x);}
    else
    printf("Input Error");
}

程序设计部分 指针(一)

第1关:指针的使用

#include <iostream>
using namespace std;

void Max(int *a, int *b, int *c)
{
    /**********   Begin   **********/
    // 比较a和b的值,如果a大于b,则交换它们的值
    if (*a > *b) {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    // 比较a和c的值,如果a大于c,则交换它们的值
    if (*a > *c) {
        int temp = *a;
        *a = *c;
        *c = temp;
    }
    // 比较b和c的值,如果b大于c,则交换它们的值
    if (*b > *c) {
        int temp = *b;
        *b = *c;
        *c = temp;
    }
    /**********   End   **********/
}

第2关:指针运算

#include <iostream>
using namespace std;
void Reverse(int *start,int *end)
{
	/**********   Begin   **********/

    while (start < end) // 当start指针小于end指针时继续交换
    {
        // 交换start和end指向的值
        int temp = *start;
        *start = *end;
        *end = temp;

        // 移动指针
        start++; // start指针向右移动
        end--;   // end指针向左移动
    }

	/**********   End   **********/
}

第3关:指针与数组

#include <iostream>
using namespace std;

void Split(int *arr,int len)
{
	/**********   Begin   **********/
    int left = 0; // 用于记录0应该放置的位置
    for (int i = 0; i < len; i++) // 遍历数组
    {
        if (arr[i] == 0) // 如果当前元素是0
        {
            // 交换arr[i]和arr[left]的值
            int temp = arr[i];
            arr[i] = arr[left];
            arr[left] = temp;
            left++; // 移动left指针
        }
    }
	/**********   End   **********/
}

程序设计部分 指针(二)


第1关:字符串与指针

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
void Shift(char *str,int k);
char m[100];
int len=0;

void Shift(char *str, int k) {
    int len = strlen(str); 
    if (len == 0) return; 
    k = k % len;
    char temp[len + 1];
    strcpy(temp, str + k);
    strcpy(temp + len - k, str); 
    temp[len] = '\0'; 
    cout << temp << endl;
}

第2关:指针与二维数组

#include <iostream>
using namespace std;

void Add()
{
    /**********   Begin   **********/
    int rows, cols;
    cin >> rows >> cols; // 读取矩阵的行数和列数

    int matrix1[rows][cols];
    int matrix2[rows][cols];
    int result[rows][cols];

    // 读取第一个矩阵的内容
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cin >> matrix1[i][j];
        }
    }

    // 读取第二个矩阵的内容
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cin >> matrix2[i][j];
        }
    }

    // 使用指针遍历两个矩阵并逐元素相加
    int *p1 = &matrix1[0][0];
    int *p2 = &matrix2[0][0];
    int *pResult = &result[0][0];

    for (int i = 0; i < rows * cols; i++) {
        *pResult = *p1 + *p2; // 计算对应元素的和
        p1++; // 移动指针到下一个元素
        p2++;
        pResult++;
    }

    // 输出结果矩阵
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cout << result[i][j] << " ";
        }
        cout << endl;
    }
    /**********   End   **********/
}

程序设计部分 指针(三)

第1关:指针作为函数参数

#include <iostream>
using namespace std;

void Sum(const int *arr,int len)
{
/**********   Begin   **********/
    if (len == 0) {
        cout << 0 << endl; // 如果数组长度为0,直接输出0
        return;
    }

    int max_value = arr[0]; // 假设第一个元素是最大值
    int sum = 0; // 初始化总和为0

    // 遍历数组,找到最大值
    for (int i = 0; i < len; i++) {
        if (arr[i] > max_value) {
            max_value = arr[i];
        }
    }

    // 遍历数组,累加所有元素的值,但排除最大值
    for (int i = 0; i < len; i++) {
        if (arr[i] != max_value) {
            sum += arr[i];
        }
    }

    // 输出结果
    cout << sum << endl;
    /**********   End   **********/
}

第2关:指针作为函数返回值

#include <iostream>
using namespace std;
/**********   Begin   **********/


int* Read(int *len)
{
    // 读取数组长度
    cin >> *len;

    // 动态分配数组
    int *arr = new int[*len];

    // 读取数组内容
    for (int i = 0; i < *len; i++) {
        cin >> arr[i];
    }

    // 返回数组指针
    return arr;
}
/**********   End   **********/

Linux之C编程入门

第1关:第一个C程序

点击打开图片
点击打开图片
点击打开图片

第2关:Linux编译C程序

点击打开图片
点击打开图片
点击打开图片

Pintos的编译、运行和调试

第1关:实验环境体验

点击打开图片
点击打开图片

Linux之线程管理

第1关:创建线程

#include <stdio.h>
#include <pthread.h>

/************************
 * 参数start_routine: 函数指针,用于指向线程函数
 * 参数arg: 是线程函数的参数
 * 返回值: 返回线程ID
*************************/
pthread_t createThread(void *(*start_routine) (void *), void *arg)
{
    pthread_t thread;
    /********** BEGIN **********/
    int ret = pthread_create(&thread, NULL, start_routine, arg);
    if (ret != 0)
    {
        printf("创建线程失败\n");
        return (pthread_t)-1; // 返回一个无效的线程ID表示失败
    }
    /********** END **********/

    return thread;
}

第2关:线程挂起

#include <stdio.h>
#include <pthread.h>

/************************
 * 参数thread: 需要等待结束的线程ID号
 * 返回值: 等待成功返回0,失败返回-1
 * 提示: 忽略线程返回值
*************************/
int waitThread(pthread_t thread)
{
    int ret = -1;
    /********** BEGIN **********/
    ret = pthread_join(thread, NULL); // 等待指定线程结束,忽略返回值
    /********** END **********/

    return ret;
}

第3关:线程终止

#include <stdio.h>
#include <pthread.h>

/************************
 * 参数thread: 需要被取消的线程ID号
 * 返回值: 成功返回0,失败返回-1
*************************/
int cancelThread(pthread_t thread)
{
    int ret = -1;
    /********** BEGIN **********/
    ret = pthread_cancel(thread); // 尝试取消指定的线程
    /********** END **********/

    return ret;
}

Linux之线程同步一

第1关:互斥锁

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

//全局互斥锁变量
extern pthread_mutex_t mutex;

//全局共享变量
extern char *buffer[3];
extern int position;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler(void *arg)
{
	/********** BEGIN **********/
	// 在修改全局变量之前加锁
	pthread_mutex_lock(&mutex);
	/********** END **********/

	buffer[position] = (char *)arg;
	sleep(1);
	position++;

	/********** BEGIN **********/
	// 修改完成后解锁
	pthread_mutex_unlock(&mutex);
	/********** END **********/

	pthread_exit(NULL);
}

第2关:自旋锁

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

//全局自旋锁变量
extern pthread_spinlock_t lock;

//全局共享变量
extern char *buffer[3];
extern int position;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler(void *arg)
{
	/********** BEGIN **********/
	// 在修改全局变量之前加锁
    pthread_spin_lock(&lock);
	/********** END **********/

	buffer[position] = (char *)arg;
	sleep(1);
	position++;

	/********** BEGIN **********/
	// 修改完成后解锁
    pthread_spin_unlock(&lock);
	/********** END **********/

	pthread_exit(NULL);
}

第3关:条件变量

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

//全局互斥锁变量和条件变量
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;

//全局共享变量
extern char *buffer[3];
extern int position;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler1(void *arg)
{
    int i;
    for(i = 0; i < 3; i++)
    {
        usleep(500);
        position++;
        // 通知ThreadHandler2函数执行赋值操作
        /********** BEGIN **********/
        pthread_cond_signal(&cond); // 通知一个等待的线程
        /********** END **********/
    }

    pthread_exit(NULL);
}

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler2(void *arg)
{
    /********** BEGIN **********/
    pthread_mutex_lock(&mutex); // 加锁
    pthread_cond_wait(&cond, &mutex); // 等待条件变量被触发
    /********** END **********/

    buffer[position] = (char *)arg;

    /********** BEGIN **********/
    pthread_mutex_unlock(&mutex); // 解锁
    /********** END **********/

    pthread_exit(NULL);
}

第4关:项目实战

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

struct Data
{
    int number;    //存放生产的数据
    struct Data *next;
};

//定义数据区头和尾
extern struct Data *beginData;    

//全局互斥锁变量和条件变量
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *Consumer(void *arg)
{
    while(1)
    {
        /********** BEGIN **********/
        pthread_mutex_lock(&mutex); // 加锁

        // 等待数据区有数据
        while (beginData == NULL)
        {
            pthread_cond_wait(&cond, &mutex); // 等待条件变量
        }

        // 消费数据
        if (beginData->number == -1)
        {
            pthread_mutex_unlock(&mutex); // 解锁
            pthread_exit(NULL); // 退出线程
        }

        printf("%d\n", beginData->number); // 打印数据

        // 从链表中删除数据
        struct Data *tmp = beginData;
        beginData = beginData->next;
        free(tmp); // 释放内存

        pthread_mutex_unlock(&mutex); // 解锁
        /********** END **********/
    }
    
    pthread_exit(NULL);
}

Linux之线程同步二

第1关:信号量

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>

//全局信号量  sem1已被初始化为1,sem2被初始化为0
extern sem_t sem1, sem2;

//全局共享变量
extern char *ch;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler1(void *arg)
{
    int i = 0;
    for(i = 0; i < 3; i++)
    {
        /********** BEGIN **********/
        sem_wait(&sem1); // 等待信号量sem1
        /********** END **********/
        
        printf("%c", *ch);
        usleep(100);
        ch++;
        
        /********** BEGIN **********/
        sem_post(&sem2); // 释放信号量sem2,让线程2运行
        /********** END **********/
    }
    
    pthread_exit(NULL);
}

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler2(void *arg)
{
    int i = 0;
    for(i = 0; i < 3; i++)
    {
        /********** BEGIN **********/
        sem_wait(&sem2); // 等待信号量sem2
        /********** END **********/
        
        printf("%c", *ch);
        ch++;
        
        /********** BEGIN **********/
        sem_post(&sem1); // 释放信号量sem1,让线程1运行
        /********** END **********/
    }
    
    pthread_exit(NULL);
}

第2关:读写锁

#include <stdio.h>
#include <pthread.h>

//全局读写锁
extern pthread_rwlock_t rwlock;

//全局共享变量
extern char buffer[3];
extern int position;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ReadHandler(void *arg)
{
    int i;
    for(i = 0; i < 3; i++)
    {
        /********** BEGIN **********/
        pthread_rwlock_rdlock(&rwlock); // 加读锁
        /********** END **********/
        
        printf("%c\n", buffer[i]);
        
        /********** BEGIN **********/
        pthread_rwlock_unlock(&rwlock); // 解锁
        /********** END **********/
        
        usleep(800);
    }
    
    pthread_exit(NULL);
}

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *WriteHandler(void *arg)
{
    /********** BEGIN **********/
    pthread_rwlock_wrlock(&rwlock); // 加写锁
    /********** END **********/
    
    buffer[position] = *(char*)arg;
    sleep(1);
    position++;
    
    /********** BEGIN **********/
    pthread_rwlock_unlock(&rwlock); // 解锁
    /********** END **********/
    
    pthread_exit(NULL);
}

第3关:项目实战

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

//记录读线程的个数
extern int reader;

//全局的信号量变量
extern sem_t sem_read, sem_write;

//读写锁初始化函数
void sem_rwlock_init()
{
	reader = 0;
	//初始化信号量
	sem_init(&sem_read, 0, 1);
	sem_init(&sem_write, 0, 1);
}

//读写锁注销函数
void sem_rwlock_destroy()
{
	sem_destroy(&sem_read);
	sem_destroy(&sem_write);
}

//读模式下的加锁操作
void sem_rwlock_rdlock()
{
	/********** BEGIN **********/
	sem_wait(&sem_read); // 等待读信号量
	reader++; // 增加读线程计数
	if (reader == 1) {
		sem_wait(&sem_write); // 如果是第一个读线程,需要等待写信号量
	}
	sem_post(&sem_read); // 释放读信号量,允许其他读线程进入
	/********** END **********/
}

//读模式下的解锁操作
void sem_rwlock_unrdlock()
{
	/********** BEGIN **********/
	sem_wait(&sem_read); // 等待读信号量
	reader--; // 减少读线程计数
	if (reader == 0) {
		sem_post(&sem_write); // 如果是最后一个读线程,释放写信号量
	}
	sem_post(&sem_read); // 释放读信号量
	/********** END **********/
}

//写模式下的加锁操作
void sem_rwlock_wrlock()
{
	sem_wait(&sem_write);
}

//写模式下的解锁操作
void sem_rwlock_unwrlock()
{
	sem_post(&sem_write);
}

Pintos基础数据结构:通用链表

第1关:通用链表的基本使用

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
typedef int tid_t;
typedef unsigned char uint8_t;
typedef void thread_action_func (struct thread *t, void *aux);

typedef bool list_less_func (const struct list_elem *a,
                             const struct list_elem *b,
                             void *aux);

#define list_entry(LIST_ELEM, STRUCT, MEMBER)           \
        ((STRUCT *) ((uint8_t *) &(LIST_ELEM)->next     \
                     - offsetof (STRUCT, MEMBER.next)))

enum thread_status
  {
    THREAD_RUNNING,     /* Running thread. */
    THREAD_READY,       /* Not running but ready to run. */
    THREAD_BLOCKED,     /* Waiting for an event to trigger. */
    THREAD_DYING        /* About to be destroyed. */
  };


struct list_elem
  {
    struct list_elem *prev;     /* Previous list element. */
    struct list_elem *next;     /* Next list element. */
  };


struct list
  {
    struct list_elem head;      /* List head. */
    struct list_elem tail;      /* List tail. */
  };

struct list mylist;

/* Inserts ELEM just before BEFORE, which may be either an
   interior element or a tail.  The latter case is equivalent to
   list_push_back(). */
void
list_insert (struct list_elem *before, struct list_elem *elem)
{
  elem->prev = before->prev;
  elem->next = before;
  before->prev->next = elem;
  before->prev = elem;
}

/* Returns the beginning of LIST.  */
struct list_elem *
list_begin (struct list *list)
{
  return list->head.next;
}

/* Returns LIST's tail.

   list_end() is often used in iterating through a list from
   front to back.  See the big comment at the top of list.h for
   an example. */
struct list_elem *
list_end (struct list *list)
{
  return &list->tail;
}


/* Returns the element after ELEM in its list.  If ELEM is the
   last element in its list, returns the list tail.  Results are
   undefined if ELEM is itself a list tail. */
struct list_elem *
list_next (struct list_elem *elem)
{
  return elem->next;
}


/* Initializes LIST as an empty list. */
void
list_init (struct list *list)
{
  list->head.prev = NULL;
  list->head.next = &list->tail;
  list->tail.prev = &list->head;
  list->tail.next = NULL;
}


/* Inserts ELEM at the end of LIST, so that it becomes the
   back in LIST. */
void
list_push_back (struct list *list, struct list_elem *elem)
{
  list_insert (list_end (list), elem);
}


struct thread
  {
    /* Owned by thread.c. */
    tid_t tid;                          /* Thread identifier. */
    enum thread_status status;          /* Thread state. */
    char name[16];                      /* Name (for debugging purposes). */
    uint8_t *stack;                     /* Saved stack pointer. */
    int priority;                       /* Priority. */
    struct list_elem allelem;           /* List element for all threads list. */

    /* Shared between thread.c and synch.c. */
    struct list_elem elem;              /* List element. */
    //此处为后添加的链表元素
    struct list_elem myelem;              /* List element. */

    /* Owned by thread.c. */
    unsigned magic;                     /* Detects stack overflow. */
  };



/*
创建 5 个 thread 结构体,为每个结构体的 tid 字段依次赋值为第二个参数数组 mytid 中的对应数值,并依次将其插入到第一个参数list 中,插入过程中要求使用自定义的字段 myelem 作为链表元素挂载到 list 中。
*/
void myinsert(struct list *list,tid_t mytid[5])
{
    list_init(list);
    for(int i=0;i<5;i++)
	{
	    /***begin 补全以下代码***/
      struct thread *new_thread; // 定义一个指向 thread 结构体的指针
      new_thread = (struct thread *)malloc(sizeof(struct thread)); // 使用 malloc 分配内存
      if (new_thread == NULL) {
          printf("Memory allocation failed\n");
          exit(1); // 如果分配失败,退出程序
      }
      new_thread->tid = mytid[i]; // 为 tid 字段赋值
      list_push_back(list, &new_thread->myelem); // 将新创建的 thread 结构体的 myelem 字段插入到链表中
		/**end**/
	}
}

第2关:通用链表的首地址计算

 #include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
typedef int tid_t;
typedef unsigned char uint8_t;
typedef void thread_action_func (struct thread *t, void *aux);

typedef bool list_less_func (const struct list_elem *a,
                             const struct list_elem *b,
                             void *aux);

#define list_entry(LIST_ELEM, STRUCT, MEMBER)           \
        ((STRUCT *) ((uint8_t *) &(LIST_ELEM)->next     \
                     - offsetof (STRUCT, MEMBER.next)))

enum thread_status
  {
    THREAD_RUNNING,     /* Running thread. */
    THREAD_READY,       /* Not running but ready to run. */
    THREAD_BLOCKED,     /* Waiting for an event to trigger. */
    THREAD_DYING        /* About to be destroyed. */
  };


struct list_elem
  {
    struct list_elem *prev;     /* Previous list element. */
    struct list_elem *next;     /* Next list element. */
  };


struct list
  {
    struct list_elem head;      /* List head. */
    struct list_elem tail;      /* List tail. */
  };

struct list mylist;

/* Inserts ELEM just before BEFORE, which may be either an
   interior element or a tail.  The latter case is equivalent to
   list_push_back(). */
void
list_insert (struct list_elem *before, struct list_elem *elem)
{
  elem->prev = before->prev;
  elem->next = before;
  before->prev->next = elem;
  before->prev = elem;
}

/* Returns the beginning of LIST.  */
struct list_elem *
list_begin (struct list *list)
{
  return list->head.next;
}

/* Returns LIST's tail.

   list_end() is often used in iterating through a list from
   front to back.  See the big comment at the top of list.h for
   an example. */
struct list_elem *
list_end (struct list *list)
{
  return &list->tail;
}


/* Returns the element after ELEM in its list.  If ELEM is the
   last element in its list, returns the list tail.  Results are
   undefined if ELEM is itself a list tail. */
struct list_elem *
list_next (struct list_elem *elem)
{
  return elem->next;
}


/* Initializes LIST as an empty list. */
void
list_init (struct list *list)
{
  list->head.prev = NULL;
  list->head.next = &list->tail;
  list->tail.prev = &list->head;
  list->tail.next = NULL;
}


/* Inserts ELEM at the end of LIST, so that it becomes the
   back in LIST. */
void
list_push_back (struct list *list, struct list_elem *elem)
{
  list_insert (list_end (list), elem);
}


struct thread
  {
    /* Owned by thread.c. */
    tid_t tid;                          /* Thread identifier. */
    enum thread_status status;          /* Thread state. */
    char name[16];                      /* Name (for debugging purposes). */
    uint8_t *stack;                     /* Saved stack pointer. */
    int priority;                       /* Priority. */
    struct list_elem allelem;           /* List element for all threads list. */

    /* Shared between thread.c and synch.c. */
    struct list_elem elem;              /* List element. */
    //此处为后添加的链表元素
    struct list_elem myelem;              /* List element. */

    /* Owned by thread.c. */
    unsigned magic;                     /* Detects stack overflow. */
  };


void
thread_foreach(thread_action_func *func, void *aux)
{
  struct list_elem *e;

  for (e = list_begin (&mylist); e != list_end (&mylist);
       e = list_next (e))
    {
      struct thread *t ;
      /****   BEGIN  补全以下代码*****/
      
      t = list_entry(e, struct thread, myelem);  // 使用 list_entry 宏获取 thread 结构体的首地址

      /****   END  *****/
      func (t, aux);
    }
}

第3关:基于函数指针的通用链表操作

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
typedef int tid_t;
typedef unsigned char uint8_t;
typedef void thread_action_func (struct thread *t, void *aux);

typedef bool list_less_func (const struct list_elem *a,
                             const struct list_elem *b,
                             void *aux);

#define list_entry(LIST_ELEM, STRUCT, MEMBER)           \
        ((STRUCT *) ((uint8_t *) &(LIST_ELEM)->next     \
                     - offsetof (STRUCT, MEMBER.next)))

enum thread_status
  {
    THREAD_RUNNING,     /* Running thread. */
    THREAD_READY,       /* Not running but ready to run. */
    THREAD_BLOCKED,     /* Waiting for an event to trigger. */
    THREAD_DYING        /* About to be destroyed. */
  };


struct list_elem
  {
    struct list_elem *prev;     /* Previous list element. */
    struct list_elem *next;     /* Next list element. */
  };


struct list
  {
    struct list_elem head;      /* List head. */
    struct list_elem tail;      /* List tail. */
  };

struct list mylist;

/* Inserts ELEM just before BEFORE, which may be either an
   interior element or a tail.  The latter case is equivalent to
   list_push_back(). */
void
list_insert (struct list_elem *before, struct list_elem *elem)
{
  elem->prev = before->prev;
  elem->next = before;
  before->prev->next = elem;
  before->prev = elem;
}

/* Returns the beginning of LIST.  */
struct list_elem *
list_begin (struct list *list)
{
  return list->head.next;
}

/* Returns LIST's tail.

   list_end() is often used in iterating through a list from
   front to back.  See the big comment at the top of list.h for
   an example. */
struct list_elem *
list_end (struct list *list)
{
  return &list->tail;
}


/* Returns the element after ELEM in its list.  If ELEM is the
   last element in its list, returns the list tail.  Results are
   undefined if ELEM is itself a list tail. */
struct list_elem *
list_next (struct list_elem *elem)
{
  return elem->next;
}


/* Initializes LIST as an empty list. */
void
list_init (struct list *list)
{
  list->head.prev = NULL;
  list->head.next = &list->tail;
  list->tail.prev = &list->head;
  list->tail.next = NULL;
}


/* Inserts ELEM at the end of LIST, so that it becomes the
   back in LIST. */
void
list_push_back (struct list *list, struct list_elem *elem)
{
  list_insert (list_end (list), elem);
}


/* Inserts ELEM in the proper position in LIST, which must be
   sorted according to LESS given auxiliary data AUX.
   Runs in O(n) average case in the number of elements in LIST. */
void
list_insert_ordered (struct list *list, struct list_elem *elem,
                     list_less_func *less, void *aux)
{
  struct list_elem *e;

  for (e = list_begin (list); e != list_end (list); e = list_next (e))
    if (less (elem, e, aux))
      break;
  return list_insert (e, elem);
}

struct thread
  {
    /* Owned by thread.c. */
    tid_t tid;                          /* Thread identifier. */
    enum thread_status status;          /* Thread state. */
    char name[16];                      /* Name (for debugging purposes). */
    uint8_t *stack;                     /* Saved stack pointer. */
    int priority;                       /* Priority. */
    struct list_elem allelem;           /* List element for all threads list. */

    /* Shared between thread.c and synch.c. */
    struct list_elem elem;              /* List element. */
    //此处为后添加的链表元素
    struct list_elem myelem;              /* List element. */

    /* Owned by thread.c. */
    unsigned magic;                     /* Detects stack overflow. */
  };

/* 自定义比较函数 */
bool
mycompare(const struct list_elem *a, const struct list_elem *b, void *aux)
{
    /***begin  补全以下代码***/
    struct thread *ta = list_entry(a, struct thread, myelem);
    struct thread *tb = list_entry(b, struct thread, myelem);
    return ta->tid < tb->tid;
    /***end***/
}

/*
创建 5 个 tcb 结构体,为每个结构体的 tid 字段赋值为第二个参数数组 mytid 中的数值,并【按序】将其插入到第一个参数list 中,插入过程中要求使用自定义的字段 myelem 作为链表元素挂载到 list 中。
*/
void myinsert(struct list *list,tid_t mytid[5])
{
    list_init(list);
    for(int i=0;i<5;i++)
    {
        /***begin 补全以下代码***/
        struct thread *t = malloc(sizeof(struct thread));
        t->tid = mytid[i];
        list_insert_ordered(list, &t->myelem, mycompare, NULL);
        /***end***/
    }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注