linux c语言,gcc基于信号机制的程序抢占型调度,用linux编一个迷你操作系统,实现了多线程的功能

拨开迷雾见分晓,一重山来一峰高

前言

这学期学习操作系统,十分激动,学习了前面内容,提及进程,不由想到在单片机中使用的free-rtos,可以很帅气地同时运行几段代码,便有了模拟的心思,期待深入学习后。
不想第一章后就有一个模拟进程调度的实验,老师也给了代码,怀着崇敬之心看代码,看见许多printf,疑惑后,发现只是单纯模拟进程的状态量。
2020带有暗淡的春,冰雪解除后也难体得温暖,无多事可作,就做了看起来简单的抢占调度。
搜索了许多,也触及了更多底层,有程序调度的堆栈过程,gcc汇编,保护现场,给一段程序分配相应栈区,linux信号机制等等。历时一周,经三次迭代,勉强见得大方之家,这里感谢无私热情的博主们。

先看结果

程序调度了3段子进程,都是类似的操作,如下

void func1(void)
{
	int i = 1;
	while (i<10) {
		i++;
		printf("thread 1 :%d\n",i);
		os_delay_ms(10);
		printf("xixi\n");
		os_delay_ms(10);
		printf("qiqi\n");
		os_delay_ms(10);
		printf("tata\n");
		os_delay_ms(100);
		printf("gaag\n");
	}
	os_exe_end();
}
void func2(void)
{
	int i = 1;
	while (i<9) {
		i++;
		printf("2thread 2 :%d\n", i);
		os_delay_ms(10);
		printf("2xixi\n");
		os_delay_ms(10);
		printf("2qiqi\n");
		os_delay_ms(10);
		printf("2tata\n");
		os_delay_ms(10);
		printf("2gaag\n");
	}
	os_exe_end();
}

void func3(void)
{
	int i = 1;
	while (i<10) {
		i++;
		printf("3thread 3 :%d\n", i);
		os_delay_ms(10);
		printf("3xixi\n");
		os_delay_ms(10);
		printf("3qiqi\n");
		os_delay_ms(10);
		printf("3tata\n");
		os_delay_ms(10);
		printf("3gaag\n");
	}
	os_exe_end();
}

最后得到的调度结果保存在一个txt下,时间单位都是ms:

p1	p2	p3
	|
	|
		|
	|
		|
	|
		|
	|
		|
|
	|
		|
|
	|
		|
|
|
	|
		|
|
	|
		|
|
	|
		|
|
	|
		|
|
	|
|
		|
|
	|
		|
|
	|
		|
|
	|
		|
|
	|
		|
|
|
	|
		|
|
	|
		|
|
	|
		|
|
	|
|
	|
|
	|
|
|
	|
|
	|
|
	|
|
	|
|
	|
|
	|
|
	|
|
	|
|
	|
|
|
	|
|
	|
|
	|
|
	|
|
	|
|
	|
|
|
pid	cputime	waittime	startTime	endTime
0	48		51			18			109	
1	36		56			13			97	
2	17		36			13			63	

整体代码可以从我的坚果云或github得到:
mini_os_3
github
下载后直接执行:

>>make
>>./main

代码分析

下面通过三个模块分析代码:
0.整体流程
1.如何保护现场与为函数分配栈区
2.如何实现程序抢占
3.os流程
4.更多有趣的东西

零.整体流程

在这里插入图片描述

一.保护现场与为函数分配栈区

推荐文章
这方面我参考了许多上述文章的内容,其中的用汇编编写的现场保护的大有裨益,应当仔细看看。

0.先看看几个寄存器(64位gcc上)

(涉及gcc汇编内容,这里说一下gcc,arm,8051的汇编的写法上指令都不尽相同,寄存器当然也有差异)
rsp:八字节栈顶指针,指向一个函数运行时的栈顶地址
rbp:八字节栈底指针,指向一个函数开始处的栈底地址
rip:八字节程序指针,指向下一条执行的命令
r12-r15:八字节通用寄存器。

1.保护现场

普通的函数调用,从一段程序跳转到另一段程序时,call指令执行时,往往在当前栈区push保存上述寄存器,之后再把rsp,rbp,rip赋予当前程序的相应值,很重要的一点就是这些操作都是“当前栈区”。中断跳转时也一样。当函数要返回调用函数retq时,首先程序一直出栈到rbp位置,之后再把上述保存的寄存器值push到相应寄存器中
通常保护现场就是保护这些寄存器。
除了上述的保护现场的方法,为了方便c语言和汇编的操作,我们也可以把寄存器保护在c语言的结构体,数组等地方,用函数调用的方法进行保护现场,例子:
汇编程序:
在下面的程序中,就利用函数的方法保留了函数执行当前的寄存器到函数输入值“rdi”之中,通过这个就可以与c语言构成关联。

.global save, restore
save:
	leaq 8(%rsp), %rdx
	movq %rdx, (0)(%rdi)
	movq %rbp, (8)(%rdi)
	# 下面这个(%rsp)取当前rsp处的值,它是谁?它是call save时压栈的save函数返回地址啊!这是关键!
	# 返回地址保存到参数的第三个8字节处,即rip字段!修改它即修改save从restore返回的地址。
	movq (%rsp), %rdx		
	movq %rdx, (16)(%rdi)
	movq %r12, (24)(%rdi)
	movq %r13, (32)(%rdi)
	movq %r14, (40)(%rdi)
	movq %r15, (48)(%rdi)
	movq $0, %rax	# 主动调用时,返回0,这个是跟setjmp学的。
	retq

restore:
	movq (0)(%rdi), %rsp
	movq (8)(%rdi), %rbp
	# 从参数第三个8字节处取出返回地址,压入到stack的rsp处,即栈顶,ret时将自动跳转到此处!
	movq (16)(%rdi), %rdx
	movq %rdx, (%rsp)
	movq (24)(%rdi), %r12
	movq (32)(%rdi), %r13
	movq (40)(%rdi), %r14
	movq (48)(%rdi), %r15
	movq $1, %rax	# 从restore返回时,返回1,这个写死了,就是1,不是别的。
	retq
————————————————
版权声明:本文为CSDN博主「dog250」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dog250/article/details/89742140

在c语言中我们可以这样构造结构体:

struct context {
	unsigned long long rsp;
	unsigned long long rbp;
	unsigned long long rip;
	unsigned long long r12;
	unsigned long long r13;
	unsigned long long r14;
	unsigned long long r15;
};

在c语言中我们就可以这样保存寄存器,这是save函数返回0,之后执行前一段内容:

struct context *rs;
rs=malloc(sizeof(struct context))
if(!save(rs))
{
...
}
else
{
...
}

通过这样跳转到我们保存的位置,这是会回到save函数的地方,返回值为1,执行后一段内容。

restore(rs)

在我的程序抢占型调度中没有用到这几个函数,用的<setjmp.h>中的:
setjmp(),与longjmp(),它们的原来都是相同的,只是<setjmp.h>考虑地更周全,也更安全一些。

1.为函数分配栈区:

我们知道,函数执行的变量,以及一些寄存器的值都会保留在栈区之中。堆区与栈区都在主存上,堆区用malloc等分配,容量较大;栈区由编译器分配,函数执行时自动出入栈,容量较小。从物理上看都在主存上,所以我们也可以自然地想到可以自定义我们的函数的栈区在堆区的某一块中,这样我们在函数之间进行跳转时就不会互相影响栈了,这里可以深入考虑一下,会有不少收获。
在上面的保护现场中我们说到过通常函数调用时:
0.call function
1.保护现场
2.把rsp,rbp,rip赋予当前程序的相应值
3.retq
这些都是在当前的栈上实现的。
那么假如我们:
0.定义一个结构体保存寄存器

struct context *rs;
rs=malloc(sizeof(struct context))

1.在堆上分配一段空间

unsigned char *stack;
stack=malloc(4096);

2.把rsp,rbp指向空间开始的位置,把rip指向一个函数的地址

rs->rip = func1;
// 因为stack是向下生长的,所以要从高地址开始!这点很容易出错。
rs->rsp = rs->rbp = stack+4000;

3.使用restore(rs)就直接转到了那个函数,其栈空间也是我们自己分配的。

restore(rs)

在我的程序抢占型调度中,使用了setjmp库与gcc内联汇编实现了上述功能,原理都是类似的。

二.如何实现程序抢占
1.linux信号机制

调用linux内核api的中断很困难,至少我没找到方法。
但linux提供了一种软中断的方式——信号机制:
信号机制在<signal.h>中。
linux信号量有许多种:
键盘输入
强制退出
定时器

在<signal.h>中有:

#define SIGHUP		 1
#define SIGINT		 2
#define SIGQUIT		 3
#define SIGILL		 4
#define SIGTRAP		 5
#define SIGABRT		 6
#define SIGIOT		 6
#define SIGBUS		 7
#define SIGFPE		 8
#define SIGKILL		 9
#define SIGUSR1		10
#define SIGSEGV		11
#define SIGUSR2		12
#define SIGPIPE		13
#define SIGALRM		14
#define SIGTERM		15
#define SIGSTKFLT	16
#define SIGCHLD		17
#define SIGCONT		18
#define SIGSTOP		19
#define SIGTSTP		20
#define SIGTTIN		21
#define SIGTTOU		22
#define SIGURG		23
#define SIGXCPU		24
#define SIGXFSZ		25
#define SIGVTALRM	26
#define SIGPROF		27
#define SIGWINCH	28
#define SIGIO		29
#define SIGPOLL		SIGIO

和中断这种资源不同,每个进程就有自己独立的信号,当信号触发时,进程会去捕获信号,并转入自己定义的信号处理函数中(如果没有,就执行编译器默认的操作)。
这里我们使用的是定时器的信号ITIMER_REAL,这个信号量需要自己设置定时的时间,时间到达了执行处理函数。
初始化在main.h中,如下:
其中的sa_flags很重要,一般它的值取0;
取0会在信号处理函数执行的时候屏蔽该信号,直到退出该处理函数。
取SA_NODEFER会在信号处理函数执行的时候不屏蔽该信号,可以再被中断。

void os_init_sigaction(void)//init signal
{
struct sigaction tact;
/*信号到了要执行的任务处理函数为prompt_info*/
tact.sa_handler =os_schedule;
tact.sa_flags = SA_NODEFER;
/*初始化信号集*/
sigemptyset(&tact.sa_mask);
/*建立信号处理机制*/
sigaction(SIGALRM, &tact, NULL);
}
void os_init_time()//init timer
{
    struct itimerval value;
    /*设定执行任务的时间间隔为0秒1*1000微秒*/
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = 1*1000;
    /*设定初始时间计数也为0秒1*1000微秒*/
    value.it_interval = value.it_value;
    /*设置计时器ITIMER_REAL*/
    setitimer(ITIMER_REAL, &value, NULL);
}
2.函数之间的抢占

!!!下面的程序一定要注意栈区的位置!!!
这里我们把信号的处理程序设置为我们的进程的管理程序:

void os_schedule(int a);

在main函数中,初始化完成后,执行while(1)等待,如下:

int main()
{
	pro1=my_malloc(sizeof(struct init_pcb));
	pro2=my_malloc(sizeof(struct init_pcb));
	pro3=my_malloc(sizeof(struct init_pcb));
	pro1->p=func1;//进程执行函数
	pro1->startTime=18;//进程开始时间,ms
	pro1->time_priority=90;//进程相对优先级,ms
	pro1->stackSpace=8000;//进程栈空间,bytes
	pro2->p=func2;
	pro2->startTime=13;
	pro2->time_priority=100;
	pro2->stackSpace=8000;
	pro3->p=func3;
	pro3->startTime=13;
	pro3->time_priority=100;
	pro3->stackSpace=8000;
	os_init_process(pro1);//初始化进程,包含分配栈存
	os_init_process(pro2);
	os_init_process(pro3);
	os_start();//初始化信号,之后while(1)
}

1ms到达后,进入:

void os_schedule(int a);

栈在主函数的栈中,当有一个程序到达了开始时间,开始此进程:

longjmp(os_now_processing->buf,1);

之后栈就会跳入我们初始化此进程所分配的栈中。
等再过了1ms,又进入:

void os_schedule(int a);

此时该中断函数的栈在此进程所分配的栈中,若此时要跳转如其它进程,则保存当前状态,进入其他进程,栈区又改变:

	if(setjmp(lastTemp->buf))//save last process
	{
		return;	
	}
	else
	{
		if(os_sleep_count==os_init_count)//all process sleep
		{
			while (1);
		}
		else
		longjmp(os_now_processing->buf,1);
	}

就这样,实现了函数之间的抢占。

三.os流程

这一部分没有什么好说的,每本操作系统的内容都比我的详细。这里简单说说:
每个进程有如下状态:

enum state{            /*枚举类型*/
	future,//还没有到达开始时间
	ready,//准备状态
	execute,//正在运行的状态
	block,//被阻塞的状态,没有用到,本来打算在os_delay_ms中用
	finish//完成
};

进程控制块pcb:

struct pcb{             /*进程控制块数据结构*/
    u16 pid;//识别号
	u32 startTime;//set :ms
    u32 save_startTime;//set :ms
	u32 endTime;
	fp32 priority;//执行优先级
	u16 timePriority;//相对优先级
    u32 sleepTime;//延时
	int waitTime;//总共等待时间
	int cputime;//set :ms,执行时间
    unsigned char* stack;
	jmp_buf buf;//setjmp变量
	enum state process_state;//进程状态
	struct pcb * next;//链表
    void (*p)(void);//函数指针
};

每隔1ms进入os_schedule(int a)中,计算优先级,安排优先级最高的程序执行,优先级按照如下计算:
执行优先级=等待时间/相对优先级+1

四.更多有趣的东西

cv_stdlib.h与cv_stdlib.c:
包含:

my_malloc(void *);
my_free(void *);
free_all();

其中:
my_malloc(void *)与malloc(void *)相同,每次分配内存就会注册记录一次指针。
my_free(void *)与free(void *)相同。
每次执行时只用多次分配,在退出程序时free_all()一次就可以了。
懒人成就理想。

五.最后贴完代码

main.c:

/* main.c */
#include "main.h"
struct init_pcb *pro1,*pro2,*pro3;
void func1(void)
{
	int i = 1;
	while (i<3) {
		i++;
		printf("thread 1 :%d\n",i);
		os_delay_ms(10);
		printf("xixi\n");
		os_delay_ms(10);
		printf("qiqi\n");
		os_delay_ms(10);
		printf("tata\n");
		os_delay_ms(10);
		printf("gaag\n");
	}
	os_exe_end();
}
void func2(void)
{
	int i = 1;
	while (i<3) {
		i++;
		printf("2thread 2 :%d\n", i);
		os_delay_ms(10);
		printf("2xixi\n");
		os_delay_ms(10);
		printf("2qiqi\n");
		os_delay_ms(10);
		printf("2tata\n");
		os_delay_ms(10);
		printf("2gaag\n");
	}
	os_exe_end();
}

void func3(void)
{
	int i = 1;
	while (i<2) {
		i++;
		printf("3thread 3 :%d\n", i);
		os_delay_ms(10);
		printf("3xixi\n");
		os_delay_ms(10);
		printf("3qiqi\n");
		os_delay_ms(10);
		printf("3tata\n");
		os_delay_ms(10);
		printf("3gaag\n");
	}
	os_exe_end();
}


int main()
{
	
	pro1=my_malloc(sizeof(struct init_pcb));
	pro2=my_malloc(sizeof(struct init_pcb));
	pro3=my_malloc(sizeof(struct init_pcb));
	pro1->p=func1;
	pro1->startTime=18;
	pro1->time_priority=90;
	pro1->stackSpace=8000;
	pro2->p=func2;
	pro2->startTime=13;
	pro2->time_priority=100;
	pro2->stackSpace=8000;
	pro3->p=func3;
	pro3->startTime=13;
	pro3->time_priority=100;
	pro3->stackSpace=8000;
	os_init_process(pro1);
	os_init_process(pro2);
	os_init_process(pro3);
	os_start();	
}

main.h:

#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include "cv_stdlib.h"
#include <unistd.h>
#include "core_head.h"
//os value declare
 struct pcb *os_head=0,*os_init_temp=0,*os_now_processing=0;
 u16 os_init_count=0,os_first_flag=0,os_end_count=0,os_sleep_count=0;
 FILE *pFile=0;
void os_schedule(int a);
int os_delay_ms_old(int delay_time);
int os_delay_ms(int delay_time);//need signal value
int os_init_process(struct init_pcb *p);
void os_schedule(int a);
void os_exe_end(void);//once a process end
void os_init_sigaction(void);//init signal
void os_init_time();//init timer
int os_start();


int os_delay_ms(int delay_time)
{
    clock_t time1;
    int delay_clock=delay_time*1000;
    time1=clock();
    while(clock()-time1<delay_clock);
    return 1;
}

int os_delay_ms2(int delay_time)//need signal value
{
    os_now_processing->sleepTime=delay_time;
	os_now_processing->process_state=block;
	os_sleep_count++;
	os_schedule(1);
    return 1;
}

int os_init_process(struct init_pcb *p)
{
	struct pcb *temp;
	unsigned long *prip1;
	unsigned long *pst1,*pbp1;
	temp=(struct pcb *)my_malloc(sizeof(struct pcb));
	if(!os_init_count)
		os_head=temp;
	else
		os_init_temp->next=temp;
	os_init_temp=temp;
	temp->startTime=p->startTime;
	temp->priority=0.0f;
	temp->timePriority=p->time_priority;
	temp->stack=(unsigned char *)my_malloc(p->stackSpace+96);
	temp->cputime=0;
	temp->waitTime=0;
	temp->sleepTime=0;
	temp->process_state=future;
	temp->save_startTime=p->startTime;
	memset(&temp->buf, 0, sizeof(jmp_buf));
	prip1 = ((unsigned long *)&temp->buf) + JB_PC;
	pbp1 = ((unsigned long *)&temp->buf) + JB_RBP;
	pst1 = ((unsigned long *)&temp->buf) + JB_RSP;
	// init process pointer
	*prip1 = PTR_MANGLE(p->p);
	*pst1 = *pbp1 = PTR_MANGLE(temp->stack+p->stackSpace);
	temp->p=p->p;
	temp->pid=os_init_count;
	os_init_count++;
	return 1;
}


void os_schedule(int a)
{
	struct pcb *temp=os_head,*lastTemp=0;
	float maxPriority=0.0f;
	u16 lastPid=-1,count1=0;
	if(os_now_processing)
	{		
		lastTemp=os_now_processing;
		lastPid=os_now_processing->pid;
	}
	while (temp)
	{
		if(temp->process_state==future)//detect boot time
		{
			if(temp->startTime)
				temp->startTime--;
			else
			{
				temp->process_state=ready;
				temp->priority=1;
				if(maxPriority<1.0f)
					{
						os_now_processing=temp;
						maxPriority=temp->priority;
						os_first_flag++;
						if(os_first_flag==1)//first process
						{
							os_first_flag++;
							longjmp(os_now_processing->buf,1);
						}
					}
			}
		}
		else if(temp->process_state==ready)
		{
			temp->waitTime++;
			temp->priority=((float)temp->waitTime/temp->timePriority+1);
			if(maxPriority<temp->priority)
			{
				os_now_processing=temp;
				maxPriority=temp->priority;
			}
		}
		else if(temp->process_state==execute)
		{
			temp->cputime++;
			if(maxPriority<temp->priority)
			{
				os_now_processing=temp;
				maxPriority=temp->priority;
			}
			temp->process_state=ready;
		}
/* 		else if(temp->process_state=block)//only sleep mode
		{
			if(!temp->sleepTime--)//sleep finished
			{
				temp->process_state=ready;
				if(maxPriority<temp->priority)
				{
					os_now_processing=temp;
					maxPriority=temp->priority;
					os_sleep_count--;
				}
			}
		} */
		temp=temp->next;
	}
	
	if(!os_now_processing)//not any process running
	{
		return;
	}
	count1=os_now_processing->pid;
	while (count1--)
		fprintf(pFile,"\t");
	fprintf(pFile,"|\n");
	os_now_processing->process_state=execute;//change statu
	if (os_now_processing->pid==lastPid)//if last processing still max priority
		return;
	if(setjmp(lastTemp->buf))//save last process
	{
		return;	
	}
	else
	{
		if(os_sleep_count==os_init_count)//all process sleep
		{
			while (1);
		}
		else
		longjmp(os_now_processing->buf,1);
	}
		
}
void os_fprint_report(void)
{
	fprintf(pFile,"pid\tcputime\twaittime\tstartTime\tendTime\n");
	struct pcb *temp=os_head;
	while (temp)
	{
	fprintf(pFile,"%u\t",temp->pid);
	fprintf(pFile,"%d\t\t",temp->cputime);
	fprintf(pFile,"%d\t\t\t",temp->waitTime);
	fprintf(pFile,"%u\t\t\t",temp->save_startTime);
	fprintf(pFile,"%u\t\n",temp->endTime);
	temp=temp->next;
	}
}
void os_exe_end(void)//once a process end
{
	os_end_count++;//sign end process num
	os_now_processing->process_state=finish;
	os_now_processing->endTime=clock()/1000;
	if(os_end_count==os_init_count)//end process num ==setup process num
	{
		printf("bye");
		os_fprint_report();
		free_all();
		fclose (pFile);
		exit(0);
	}
	os_schedule(0);
	while (1);
}
void os_init_sigaction(void)//init signal
{
struct sigaction tact;
/*信号到了要执行的任务处理函数为prompt_info*/
tact.sa_handler =os_schedule;
tact.sa_flags = SA_NODEFER;
/*初始化信号集*/
sigemptyset(&tact.sa_mask);
/*建立信号处理机制*/
sigaction(SIGALRM, &tact, NULL);
}

void os_init_time()//init timer
{
    struct itimerval value;
    /*设定执行任务的时间间隔为2秒0微秒*/
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = 1*1000;
    /*设定初始时间计数也为2秒0微秒*/
    value.it_interval = value.it_value;
    /*设置计时器ITIMER_REAL*/
    setitimer(ITIMER_REAL, &value, NULL);
}
int os_start()
{
	pFile = fopen ("os_report.txt","w");//output file
	fprintf(pFile,"p1\tp2\tp3\n");
	os_init_sigaction();
	os_init_time();
	while (1);
}

os_core.h:

#include "stdio.h"
#include "setjmp.h"
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef float fp32;
typedef double fp64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t  u8;
typedef uint8_t bool_t;
#define JB_RBP        1
#define JB_RSP        6
#define JB_PC        7

enum state{            /*枚举类型*/
	future,
	ready,
	execute,
	block,
	finish
};
struct pcb{             /*进程控制块数据结构*/
    u16 pid;
	u32 startTime;//set :ms
    u32 save_startTime;//set :ms
	u32 endTime;
	fp32 priority;
	u16 timePriority;
    u32 sleepTime;
	int waitTime;
	int cputime;//set :ms
    unsigned char* stack;
	jmp_buf buf;
	enum state process_state;
	struct pcb * next;
    void (*p)(void);
};

struct init_pcb{
    u32 startTime;//ms
    u32 stackSpace;//bytes
    u32 time_priority;//ms
    void (*p)(void);//processing function
};
unsigned long PTR_MANGLE(unsigned long var)//init stack
{
    asm (   "movq %1, %%rdx \n"
            "xor    %%fs:0x30, %%rdx\n"
            "rol    $0x11,%%rdx\n"
            "movq %%rdx, %0\t\n"
            : "=r" (var)
            :"0" (var));
    return var;
}
unsigned long PTR_DEMANGLE(unsigned long var)//init stack
{
    asm (   "ror $0x11, %0\n"
            "xor %%fs:0x30, %0"
            : "=r" (var)
            : "0" (var));
    return var;
}

cv_stdlib.c:

//64 bits complier
#include"cv_stdlib.h"

static unsigned int mallocLength=0,SECTORNUM=0,countPublic=0;
static unsigned long long *mallocList,*head;
void free_all()
{
    void *pointer=0,*pointer2=0;
    int count;
    
    for(;mallocLength;)
    {
        for(count=0;count<SECTOR_SIZE-1 && mallocLength;count++)
        {
            pointer=head[count];
            free(pointer);
            pointer=0;
            mallocLength--;
        }
        pointer2=head;
        if(mallocLength)
            head=head[SECTOR_SIZE-1];
        free(pointer2);
        pointer2=0;
    }
    return;
}

void mallocList_append(unsigned long long address)
{
    unsigned int *pointer=0;
    if(!SECTORNUM)
    {
        pointer=(unsigned int *)malloc(SECTOR_SIZE*8);
        head=pointer;
        mallocList=head;
        SECTORNUM=1;
    }
    if(countPublic<SECTOR_SIZE-1)
    {
        mallocList[countPublic]=address;
        countPublic++;
        mallocLength++;
    }
    else
    {
        pointer=(unsigned int *)malloc(sizeof(void *));
        mallocList[SECTOR_SIZE-1]=pointer;
        mallocList=pointer;
        countPublic=0;
        SECTORNUM++;
        mallocList[countPublic]=address;
        countPublic++;
        mallocLength++;
    }
}

void *my_malloc(unsigned int uSize)
{
    void *pointer=0;
    pointer=malloc(uSize);
    mallocList_append(pointer);
    return pointer;
}

void my_free(void *pPtr)
{
    free(pPtr);
    pPtr=(unsigned char)malloc(1);
    return;
}

cv_stdlib.h:

#ifndef CV_STDLIB_H
#define CV_STDLIB_H
#include "stdlib.h"
#include "stdio.h"

#define SECTOR_SIZE 64

extern void my_free(void *pPtr);
extern void *my_malloc(unsigned int uSize);
extern void free_all();

#endif // MAIN_H

makeFile:

main: main.o cv_stdlib.o 
	gcc main.o cv_stdlib.o  -o main
 
main.o: main.c main.h
	gcc -c main.c

cv_stdlib.o : cv_stdlib.c cv_stdlib.h
	gcc -c cv_stdlib.c

不行了,太累了,以后有时间完善完善,水平有限,欢迎执正批评。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值