实验三 同步与通信
16281042 李许增
操作系统:arch Linux
一、通过fork的方式,产生4个进程P1,P2,P3,P4,每个进程打印输出自己的名字,例如P1输出“I am the process P1”。要求P1最先执行,P2、P3互斥执行,P4最后执行。通过多次测试验证实现是否正确。
实验代码(fork.c)
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
sem_t *a_sem, *b_sem, *c_sem, *d_sem;
int main()
{
a_sem = sem_open("asem", O_CREAT, 0666, 0);
b_sem = sem_open("bsem", O_CREAT, 0666, 0);
c_sem = sem_open("csem", O_CREAT, 0666, 0);
pid_t fork_pid;//fork函数返回值
printf("我是进程P1\n");
sleep(1);
sem_post(a_sem);
fork_pid = fork();
if(fork_pid == 0)
{
sem_wait(a_sem);
printf("我是进程P2\n");
sleep(1);
sem_post(a_sem);
sem_post(b_sem);
}
else
{
fork_pid = fork();
if(fork_pid == 0)
{
sem_wait(a_sem);
printf("我是进程P3\n");
sleep(1);
sem_post(a_sem);
sem_post(c_sem);
}
else
{
fork_pid = fork();
if(fork_pid == 0)
{
sem_wait(b_sem);
sem_wait(c_sem);
printf("我是进程P4\n");
sleep(1);
sem_post(b_sem);
sem_post(c_sem);
}
else
{}
}
}
sem_close(a_sem);
sem_close(b_sem);
sem_close(c_sem);
unlink("asem");
unlink("bsem");
unlink("csem");
return 0;
}
实验结果
二、火车票余票数ticketCount 初始值为1000,有一个售票线程,一个退票线程,各循环执行多次。添加同步机制,使得结果始终正确。要求多次测试添加同步机制前后的实验效果。(说明:为了更容易产生并发错误,可以在适当的位置增加一些pthread_yield(),放弃CPU,并强制线程频繁切换)
首先进行不添加信号量控制进行测试:
实验代码(ticket.c)
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int ticketcount = 1000;
int temp;
void *saller() {
int i = 500;
while(i > 0)
{
temp = ticketcount;
pthread_yield();
temp = temp - 1;
pthread_yield();
ticketcount = temp;
i--;
}
return NULL;
}
void *refund_ticket(){
int i = 500;
while(i > 0)
{
temp = ticketcount;
pthread_yield();
temp = temp + 1;
pthread_yield();
ticketcount = temp;
i--;
}
return NULL;
}
int main()
{
pthread_t p1, p2;
pthread_create(&p1, NULL, saller, NULL);
pthread_create(&p2, NULL, refund_ticket, NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("火车票余量 : %d\n", ticketcount);
return 0;
}
不添加信号量实验结果
我们能再函数体内设置退票人数为500,购票人数为500,则最终票的数目结果应该为1000
由于进程并发执行对与共享变量temp的操作有冲突,所以会出现错误,ticketcount输出不为1000
进行添加信号量的测试
实验代码(ticket_sem.c)
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int ticketcount = 1000;
int temp;
sem_t * mysem = NULL;
void *saller() {
int i = 500;
while(i > 0)
{
sem_wait(mysem);
temp = ticketcount;
pthread_yield();
temp = temp - 1;
pthread_yield();
ticketcount = temp;
i--;
sem_post(mysem);
}
return NULL;
}
void *refund_ticket(){
int i = 500;
while(i > 0)
{
sem_wait(mysem);
temp = ticketcount;
pthread_yield();
temp = temp + 1;
pthread_yield();
ticketcount = temp;
i--;
sem_post(mysem);
}
return NULL;
}
int main()
{
mysem = sem_open("csem",O_CREAT,0666,1);
pthread_t p1, p2;
pthread_create(&p1, NULL, saller, NULL);
pthread_create(&p2, NULL, refund_ticket, NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("火车票余量 : %d\n", ticketcount);
sem_close(mysem);
unlink("csem");
return 0;
}
当我们互斥添加信号量进行控制后输出正常
实验结果:
三、一个生产者一个消费者线程同步。设置一个线程共享的缓冲区, char buf[10]。一个线程不断从键盘输入字符到buf,一个线程不断的把buf的内容输出到显示器。要求输出的和输入的字符和顺序完全一致。(在输出线程中,每次输出睡眠一秒钟,然后以不同的速度输入测试输出是否正确)。要求多次测试添加同步机制前后的实验效果。
首先进行不添加信号量的测试
实验代码(buff_share.c):
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
char buff[10];
int i = 0, j = 9;
//sem_t * mysem = NULL;
void *work1()
{
while(1)
{
scanf("%c\n",&buff[i]);
i++;
i = i%10;
}
return NULL;
}
void *work2()
{
while(1)
{
if(((j + 1)% 10) != i)
{
printf("我是输出:%c\n",buff[(j + 1) % 10]);
sleep(1);
j++;
j = j%10;
}
}
return NULL;
}
int main(int argc, char *argv[])
{
//mysem = sem_open("csem",O_CREAT,0666,1);
pthread_t p1, p2;
pthread_create(&p1, NULL, work1, NULL);
pthread_create(&p2, NULL, work2, NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
//sem_close(mysem);
//unlink("csem");
return 0;
}
由于没有添加信号量导致如果输入快于输出,且比输出快设置的数组大小(本代码中为10个字符),那么原来存在于数组中的字符在没有数出来的情况下会被后面读进的字符覆盖掉。
实验结果:
我们可以看出在q之后的"ertyuiopa"等字符被覆盖
正常速度输入:
下面进行添加信号量控制的测试:
实验代码(sem_buff_share.c):
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
char buff[10];
int i = 0, j = 0;
sem_t * sem_place = NULL;
sem_t * sem_data = NULL;
void *work1()
{
while(1)
{
sem_wait(sem_place);//消耗空间资源wait操作
scanf("%c\n",&buff[i]);
sem_post(sem_data);//释放data资源signal操作
i++;
i = i%10;
}
return NULL;
}
void *work2()
{
while(1)
{
sem_wait(sem_data);//消耗data资源wait操作
printf("我是输出:%c\n",buff[j]);
sem_post(sem_place);//释放空间资源signal操作
sleep(1);
j++;
j = j%10;
}
return NULL;
}
int main()
{
sem_place = sem_open("placesem",O_CREAT,0666,10);//空间资源初始化为10
sem_data = sem_open("datasem",O_CREAT,0666,0);//data资源初始化为0
pthread_t p1, p2;
pthread_create(&p1, NULL, work1, NULL);
pthread_create(&p2, NULL, work2, NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
sem_close(sem_place);
sem_close(sem_data);
unlink("placesem");
unlink("datasem");
return 0;
}
本题为操作系统中的生产者和消费者问题,需要设置关于数组空间的信号量sem_place(初始值为10),和有关数组中字符个数的信号量sem_data(初始值为0).
实验结果
我们可以看到即使输入比输出快出整个数组的字符个数也不会出现错误。
四、进程通信问题。阅读并运行共享内存、管道、消息队列三种机制的代码
a)通过实验测试,验证共享内存的代码中,receiver能否正确读出sender发送的字符串?如果把其中互斥的代码删除,观察实验结果有何不同?如果在发送和接收进程中打印输出共享内存地址,他们是否相同,为什么?
首先是信号量存在的情况,程序能正常运行,receiver可以正确读出sender发送的字符串。
实验代码(sender.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
int main(int argc, char *argv[])
{
key_t key;
int shm_id;
int sem_id;
int value = 0;
//1.Product the key
key = ftok(".", 0xFF);
//2. Creat semaphore for visit the shared memory
sem_id = semget(key, 1, IPC_CREAT|0644);
if(-1 == sem_id)
{
perror("semget");
exit(EXIT_FAILURE);
}
//3. init the semaphore, sem=0
if(-1 == (semctl(sem_id, 0, SETVAL, value)))
{
perror("semctl");
exit(EXIT_FAILURE);
}
//4. Creat the shared memory(1K bytes)
shm_id = shmget(key, 1024, IPC_CREAT|0644);
if(-1 == shm_id)
{
perror("shmget");
exit(EXIT_FAILURE);
}
printf("sender共享内存地址:%d",shm_id);
//5. attach the shm_id to this process
char *shm_ptr;
shm_ptr = shmat(shm_id, NULL, 0);
if(NULL == shm_ptr)
{
perror("shmat");
exit(EXIT_FAILURE);
}
//6. Operation procedure
struct sembuf sem_b;
sem_b.sem_num = 0; //first sem(index=0)
sem_b.sem_flg = SEM_UNDO;
sem_b.sem_op = 1; //Increase 1,make sem=1
while(1)
{
if(0 == (value = semctl(sem_id, 0, GETVAL)))
{
printf("\nNow, snd message process running:\n");
printf("\tInput the snd message: ");
scanf("%s", shm_ptr);
if(-1 == semop(sem_id, &sem_b, 1))
{
perror("semop");
exit(EXIT_FAILURE);
}
}
//if enter "end", then end the process
if(0 == (strcmp(shm_ptr ,"end")))
{
printf("\nExit sender process now!\n");
break;
}
}
shmdt(shm_ptr);
return 0;
}
实验代码(receiver.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
int main(int argc, char *argv[])
{
key_t key;
int shm_id;
int sem_id;
int value = 0;
//1.Product the key
key = ftok(".", 0xFF);
//2. Creat semaphore for visit the shared memory
sem_id = semget(key, 1, IPC_CREAT|0644);
if(-1 == sem_id)
{
perror("semget");
exit(EXIT_FAILURE);
}
//3. init the semaphore, sem=0
if(-1 == (semctl(sem_id, 0, SETVAL, value)))
{
perror("semctl");
exit(EXIT_FAILURE);
}
//4. Creat the shared memory(1K bytes)
shm_id = shmget(key, 1024, IPC_CREAT|0644);
if(-1 == shm_id)
{
perror("shmget");
exit(EXIT_FAILURE);
}
printf("receiver共享内存地址:%d",shm_id);
//5. attach the shm_id to this process
char *shm_ptr;
shm_ptr = shmat(shm_id, NULL, 0);
if(NULL == shm_ptr)
{
perror("shmat");
exit(EXIT_FAILURE);
}
//6. Operation procedure
struct sembuf sem_b;
sem_b.sem_num = 0; //first sem(index=0)
sem_b.sem_flg = SEM_UNDO;
sem_b.sem_op = -1; //Increase 1,make sem=1
while(1)
{
if(1 == (value = semctl(sem_id, 0, GETVAL)))
{
printf("\nNow, receive message process running:\n");
printf("\tThe message is : %s\n", shm_ptr);
if(-1 == semop(sem_id, &sem_b, 1))
{
perror("semop");
exit(EXIT_FAILURE);
}
}
//if enter "end", then end the process
if(0 == (strcmp(shm_ptr ,"end")))
{
printf("\nExit the receiver process now!\n");
break;
}
}
shmdt(shm_ptr);
//7. delete the shared memory
if(-1 == shmctl(shm_id, IPC_RMID, NULL))
{
perror("shmctl");
exit(EXIT_FAILURE);
}
//8. delete the semaphore
if(-1 == semctl(sem_id, 0, IPC_RMID))
{
perror("semctl");
exit(EXIT_FAILURE);
}
return 0;
}
测试结果
接着我们去掉程序中的信号量,receiver不能正常接收到sender发送的数据:
实验代码(nosem_sender.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
int main(int argc, char *argv[])
{
key_t key;
int shm_id;
int sem_id;
int value = 0;
//1.Product the key
key = ftok(".", 0xFF);
//2. Creat semaphore for visit the shared memory
/*sem_id = semget(key, 1, IPC_CREAT|0644);
if(-1 == sem_id)
{
perror("semget");
exit(EXIT_FAILURE);
}*/
//3. init the semaphore, sem=0
/*if(-1 == (semctl(sem_id, 0, SETVAL, value)))
{
perror("semctl");
exit(EXIT_FAILURE);
}*/
//4. Creat the shared memory(1K bytes)
shm_id = shmget(key, 1024, IPC_CREAT|0644);
if(-1 == shm_id)
{
perror("shmget");
exit(EXIT_FAILURE);
}
//5. attach the shm_id to this process
char *shm_ptr;
shm_ptr = shmat(shm_id, NULL, 0);
if(NULL == shm_ptr)
{
perror("shmat");
exit(EXIT_FAILURE);
}
//6. Operation procedure
/*struct sembuf sem_b;
sem_b.sem_num = 0; //first sem(index=0)
sem_b.sem_flg = SEM_UNDO;
sem_b.sem_op = 1; //Increase 1,make sem=1*/
while(1)
{
//if(0 == (value = semctl(sem_id, 0, GETVAL)))
{
printf("\nNow, snd message process running:\n");
printf("\tInput the snd message: ");
scanf("%s", shm_ptr);
/*if(-1 == semop(sem_id, &sem_b, 1))
{
perror("semop");
exit(EXIT_FAILURE);
}*/
}
//if enter "end", then end the process
if(0 == (strcmp(shm_ptr ,"end")))
{
printf("\nExit sender process now!\n");
break;
}
}
shmdt(shm_ptr);
return 0;
}
实验代码(nosem_receiver.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
int main(int argc, char *argv[])
{
key_t key;
int shm_id;
//int sem_id;
int value = 0;
//1.Product the key
key = ftok(".", 0xFF);
//2. Creat semaphore for visit the shared memory
/*sem_id = semget(key, 1, IPC_CREAT|0644);
if(-1 == sem_id)
{
perror("semget");
exit(EXIT_FAILURE);
}*/
//3. init the semaphore, sem=0
/*if(-1 == (semctl(sem_id, 0, SETVAL, value)))
{
perror("semctl");
exit(EXIT_FAILURE);
}*/
//4. Creat the shared memory(1K bytes)
shm_id = shmget(key, 1024, IPC_CREAT|0644);
if(-1 == shm_id)
{
perror("shmget");
exit(EXIT_FAILURE);
}
//5. attach the shm_id to this process
char *shm_ptr;
shm_ptr = shmat(shm_id, NULL, 0);
if(NULL == shm_ptr)
{
perror("shmat");
exit(EXIT_FAILURE);
}
//6. Operation procedure
/*struct sembuf sem_b;
sem_b.sem_num = 0; //first sem(index=0)
sem_b.sem_flg = SEM_UNDO;
sem_b.sem_op = -1; //Increase 1,make sem=1*/
while(1)
{
//if(1 == (value = semctl(sem_id, 0, GETVAL)))
{
printf("\nNow, receive message process running:\n");
printf("\tThe message is : %s\n", shm_ptr);
sleep(5);
/*if(-1 == semop(sem_id, &sem_b, 1))
{
perror("semop");
exit(EXIT_FAILURE);
}*/
}
//if enter "end", then end the process
if(0 == (strcmp(shm_ptr ,"end")))
{
printf("\nExit the receiver process now!\n");
break;
}
}
shmdt(shm_ptr);
//7. delete the shared memory
if(-1 == shmctl(shm_id, IPC_RMID, NULL))
{
perror("shmctl");
exit(EXIT_FAILURE);
}
//8. delete the semaphore
/*if(-1 == semctl(sem_id, 0, IPC_RMID))
{
perror("semctl");
exit(EXIT_FAILURE);
}*/
return 0;
}
实验结果:
当sender不发送数据时receiver会从缓冲区继续读之前的数据,导致错误发生。
输出共享内存地址相同:
实验结果:
共享内存区域是被多个进程共享的一部分物理内存。多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信。
b)有名管道和无名管道通信系统调用是否已经实现了同步机制?通过实验验证,发送者和接收者如何同步的。比如,在什么情况下,发送者会阻塞,什么情况下,接收者会阻塞?
实验代码(pipe.c)
#include <stdio.h>
#include <unistd.h> //for pipe()
#include <string.h> //for memset()
#include <stdlib.h> //for exit()
int main()
{
int fd[2];
char buf[20];
if(-1 == pipe(fd))
{
perror("pipe");
exit(EXIT_FAILURE);
}
write(fd[1], "hello,world", 12);
memset(buf, '\0', sizeof(buf));
read(fd[0], buf, 12);
printf("The message is: %s\n", buf);
return 0;
}
实验代码(fifo_send.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h>
#define FIFO "/tmp/my_fifo"
int main()
{
char buf[] = "hello,world";
//`. check the fifo file existed or not
int ret;
ret = access(FIFO, F_OK);
if(ret == 0) //file /tmp/my_fifo existed
{
system("rm -rf /tmp/my_fifo");
}
//2. creat a fifo file
if(-1 == mkfifo(FIFO, 0766))
{
perror("mkfifo");
exit(EXIT_FAILURE);
}
//3.Open the fifo file
int fifo_fd;
fifo_fd = open(FIFO, O_WRONLY);
if(-1 == fifo_fd)
{
perror("open");
exit(EXIT_FAILURE);
}
//4. write the fifo file
int num = 0;
num = write(fifo_fd, buf, sizeof(buf));
if(num < sizeof(buf))
{
perror("write");
exit(EXIT_FAILURE);
}
printf("write the message ok!\n");
close(fifo_fd);
return 0;
}
实验代码(fifo_rcv.c)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h>
#define FIFO "/tmp/my_fifo"
int main()
{
char buf[20] ;
memset(buf, '\0', sizeof(buf));
//`. check the fifo file existed or not
int ret;
ret = access(FIFO, F_OK);
if(ret != 0) //file /tmp/my_fifo existed
{
fprintf(stderr, "FIFO %s does not existed", FIFO);
exit(EXIT_FAILURE);
}
//2.Open the fifo file
int fifo_fd;
fifo_fd = open(FIFO, O_RDONLY);
if(-1 == fifo_fd)
{
perror("open");
exit(EXIT_FAILURE);
}
//4. read the fifo file
int num = 0;
num = read(fifo_fd, buf, sizeof(buf));
printf("Read %d words: %s\n", num, buf);
close(fifo_fd);
return 0;
}
实验结果:
有名管道和无名管道通信系统调用已经实现了同步机制,我们可以看出当接收方未启动时那么发送方会阻塞等待,如果发送方未启动时那么接收方会阻塞等待。
c)消息通信系统调用是否已经实现了同步机制?通过实验验证,发送者和接收者如何同步的。比如,在什么情况下,发送者会阻塞,什么情况下,接收者会阻塞?
实验代码(client.c):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#define BUF_SIZE 128
//Rebuild the strcut (must be)
struct msgbuf
{
long mtype;
char mtext[BUF_SIZE];
};
int main(int argc, char *argv[])
{
//1. creat a mseg queue
key_t key;
int msgId;
printf("THe process(%s),pid=%d started~\n", argv[0], getpid());
key = ftok(".", 0xFF);
msgId = msgget(key, IPC_CREAT|0644);
if(-1 == msgId)
{
perror("msgget");
exit(EXIT_FAILURE);
}
//2. creat a sub process, wait the server message
pid_t pid;
if(-1 == (pid = fork()))
{
perror("vfork");
exit(EXIT_FAILURE);
}
//In child process
if(0 == pid)
{
while(1)
{
alarm(0);
alarm(100); //if doesn't receive messge in 100s, timeout & exit
struct msgbuf rcvBuf;
memset(&rcvBuf, '\0', sizeof(struct msgbuf));
msgrcv(msgId, &rcvBuf, BUF_SIZE, 2, 0);
printf("Server said: %s\n", rcvBuf.mtext);
}
exit(EXIT_SUCCESS);
}
else //parent process
{
while(1)
{
usleep(100);
struct msgbuf sndBuf;
memset(&sndBuf, '\0', sizeof(sndBuf));
char buf[BUF_SIZE] ;
memset(buf, '\0', sizeof(buf));
printf("\nInput snd mesg: ");
scanf("%s", buf);
strncpy(sndBuf.mtext, buf, strlen(buf)+1);
sndBuf.mtype = 1;
if(-1 == msgsnd(msgId, &sndBuf, strlen(buf)+1, 0))
{
perror("msgsnd");
exit(EXIT_FAILURE);
}
//if scanf "end~", exit
if(!strcmp("end~", buf))
break;
}
printf("THe process(%s),pid=%d exit~\n", argv[0], getpid());
}
return 0;
}
实验代码(server.c):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#define BUF_SIZE 128
//Rebuild the strcut (must be)
struct msgbuf
{
long mtype;
char mtext[BUF_SIZE];
};
int main(int argc, char *argv[])
{
//1. creat a mseg queue
key_t key;
int msgId;
key = ftok(".", 0xFF);
msgId = msgget(key, IPC_CREAT|0644);
if(-1 == msgId)
{
perror("msgget");
exit(EXIT_FAILURE);
}
printf("Process (%s) is started, pid=%d\n", argv[0], getpid());
while(1)
{
alarm(0);
alarm(600); //if doesn't receive messge in 600s, timeout & exit
struct msgbuf rcvBuf;
memset(&rcvBuf, '\0', sizeof(struct msgbuf));
msgrcv(msgId, &rcvBuf, BUF_SIZE, 1, 0);
printf("Receive msg: %s\n", rcvBuf.mtext);
struct msgbuf sndBuf;
memset(&sndBuf, '\0', sizeof(sndBuf));
strncpy((sndBuf.mtext), (rcvBuf.mtext), strlen(rcvBuf.mtext)+1);
sndBuf.mtype = 2;
if(-1 == msgsnd(msgId, &sndBuf, strlen(rcvBuf.mtext)+1, 0))
{
perror("msgsnd");
exit(EXIT_FAILURE);
}
//if scanf "end~", exit
if(!strcmp("end~", rcvBuf.mtext))
break;
}
printf("THe process(%s),pid=%d exit~\n", argv[0], getpid());
return 0;
}
实验结果
正常运行:
服务器端未打开:
客户端进入阻塞
客户端未打开:
服务器端进入阻塞
消息通信系统调用已经实现了同步机制。
五、阅读Pintos操作系统,找到并阅读进程上下文切换的代码,说明实现的保存和恢复的上下文内容以及进程切换的工作流程。
首先将寄存器压入栈顶:pushl %ebp,接着将进程的栈指针存储在构造的struct thread中,并且提前获取在结构体中的内存地址偏移量因为汇编中无法直接获取结构体中的栈指针,在知道结构体偏移量之后还需要获取当前进程在内存中的偏移量这样才能获取堆栈的位置,在实现进程上下文切换的函数中本身就将当前进程指针和要进行进程切换的指针作为参数那么只需要直接进行访问就行,在了解以上信息后就可以计算在整个内存中栈的地址了,这是正在运行进程的保存过程,恢复过程就是保存过程的逆操作,只要找到地址将栈中的信息pop出来就可以做到恢复。
git代码
参考文章:
https://www.cnblogs.com/Jimmy1988/p/7706980.html
https://www.cnblogs.com/Jimmy1988/p/7699351.html
https://www.cnblogs.com/Jimmy1988/p/7553069.html