一,关于PV操作
p操作:当一个进程对对信号量mutex执行p操作时,执行两个动作:
mutex.valu–; //申请一个资源
if (mutex.value<0) //申请失败
sleep(); //本进程进入该信号量等待队列睡眠
v操作:当一个进程对对信号量mutex执行v操作时,执行两个动作:
mutex.value++; //释放一个资源
if (mutex.value>=0) //如果有进程在等待使用本进程
wakeup(); //从该信号量的等待队列中唤醒一个进程
当信号量mutex.value小于0时,其绝对值表示系统中因请求该类资源而被阻塞的进程数目.mutex.value大于0时表示可用的临界资源数。
PV操作实现的功能:
实现进程之间的互斥,实现进程之间的同步
区别:互斥是为了保证临界区一次只能由一个进程使用;而同步是为了实现进程通信,即传递资源当前的态是否适合一个进程使用。
实例:
1. 互斥:进出教室问题:有一个变量count,初值为0,一个学生进入教室则count++,出教室则count–。
过程:一个学生进入教室执行IN,p操作,mutex.value = 0;假设在进行count++之前遇到了中断,而中断之后跳回来时正好这个学生又在出教室,那么这时候就会执行OUT,mutex.value = -1,该OUT进程进入睡眠,返回IN进程,count = 1,v操作,mutex.value = 0(说明有等待使用count的进程);唤醒OUT进程,count = 0,v操作,mutex.value = 1。
注意上面划线部分的假设。PV操作在这就是为了保证这种竞争情况的发生。
mutex = 1; count = 0; IN() { p(mutex); count++; v(mutex); } OUT() { p(mutex); count--; v(mutex); }
2. 同步:桌上有一空盘,允许存放一只水果。爸爸可向盘中放苹果,也可向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时一次只能放一只水果供吃者取用,请用P、V原语实现爸爸、儿子、女儿三个并发进程的同步。
分析:在本题中,爸爸、儿子、女儿共用一个盘子,盘中一次只能放一个水果。当盘子为空时,爸爸可将一个水果放入果盘中。若放入果盘中的是桔子,则允许儿子吃,女儿必须等待;若放入果盘中的是苹果,则允许女儿吃,儿子必须等待。本题实际上是生产者-消费者问题的一种变形。这里,生产者放入缓冲区的产品有两类,消费者也有两类,每类消费者只消费其中固定的一类产品。
解:在本题中,应设置三个信号量S、So、Sa,信号量S表示盘子是否为空,其初值为l;信号量So表示盘中是否有桔子,其初值为0;信号量Sa表示盘中是否有苹果,其初值为0。
int S=1; int Sa=0; int So=0; main() { father(); /*父亲进程*/ son(); /*儿子进程*/ daughter(); /*女儿进程*/ } father() { P(S); 将水果放入盘中; if(放入的是桔子)V(So); else V(Sa); } son() { P(So); 从盘中取出桔子; V(S); 吃桔子; } daughter() { P(Sa); 从盘中取出苹果; V(S); 吃苹果; }
http://www.cnblogs.com/CareySon/archive/2012/04/14/Process-SynAndmutex.html
#include <windows.h> #include <cstdio> #include <iostream> using namespace std; #define MAXN 20 struct ThreadInfo { int num; bool type; double delay, time; } thread_info[MAXN]; HANDLE Mutex; HANDLE thread[MAXN]; int readcount; double totaltime; void W_P(int Process_num) { //临界区 printf("Thread %d 开始写入 ", Process_num); Sleep((DWORD) thread_info[Process_num].time * 1000); printf("Thread %d 写入完成 ", Process_num); } void R_P(int Process_num) { //临界区 printf("Thread %d 开始读入 ", Process_num); Sleep((DWORD) thread_info[Process_num].time * 1000); printf("Thread %d 读入完成 ", Process_num); } DWORD WINAPI reader(LPVOID lpVoid) { int Process_num = *(int*) lpVoid; //用来检测reader事件的信号状态 Sleep((DWORD) thread_info[Process_num].delay * 1000); printf("Thread %d 请求读 ", Process_num); readcount++; if (readcount == 1) //之前没有读者,P操作占用资源 WaitForSingleObject(Mutex, INFINITE); R_P(Process_num); //之前有读者,不必P操作 readcount--; if (readcount == 0) //读者全部执行结束,V操作释放资源 ReleaseSemaphore(Mutex, 1, NULL); //读者优先,只有没有读者的时候才可以写 return Process_num; } DWORD WINAPI writer(LPVOID lpVoid) { int Process_num = *(int*) lpVoid; Sleep((DWORD) thread_info[Process_num].delay * 1000); printf("Thread %d 请求写 ", Process_num); WaitForSingleObject(Mutex, INFINITE); W_P(Process_num); ReleaseSemaphore(Mutex, 1, NULL); return Process_num; } int main() { freopen("data_tmp.txt", "r", stdin); Mutex = CreateSemaphore(NULL, 1, 1, NULL); //增加一个信号量,初始值为1,最大值为1 readcount = 0; totaltime = 0; char type[10]; int num = -1; while (~scanf("%s", type)) { num++; thread_info[num].num = num; if (strcmp(type, "write") == 0) thread_info[num].type = 0; else thread_info[num].type = 1; scanf("%lf%lf", &thread_info[num].delay, &thread_info[num].time); totaltime += thread_info[num].time; if (thread_info[num].type == 0) { printf("创建写进程 %d ", thread_info[num].num); thread[num] = CreateThread(NULL, 0, writer, &thread_info[num].num, 0, 0); //创建线程执行写者函数,会与程序并发执行 //多个线程之间如果公用了一些资源的话,我们并不能保证这些资源都能正确地被利用,因为这个时候资源并不是独占的 //需要PV操作進行約束 } else { printf("创建读进程 %d ", thread_info[num].num); thread[num] = CreateThread(NULL, 0, reader, &thread_info[num].num, 0, 0); } } Sleep((DWORD) 20 * 1000); return 1; } /* write 1 8 read 0 4 read 3 5 write 3 5 */ /* 创建写进程 0 创建读进程 1 创建读进程 2 创建写进程 3 Thread 1 请求读 Thread 1 开始读入 Thread 0 请求写 Thread 3 请求写 Thread 2 请求读 Thread 2 开始读入 Thread 1 读入完成 Thread 2 读入完成 Thread 0 开始写入 Thread 0 写入完成 Thread 3 开始写入 */
二,磁盘空间管理
内存池实现:
mem_pool -> mem_block -> mem_node
空白盘区链:通过维护free链表实现对内存碎片的整理
通过mem_block实现空白盘区目录功能
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define BUF_SIZE 100 #define BASE_COUNT 10000 #define STEP_COUNT 1000 typedef union _mem_node { union _mem_node *next; char buf[BUF_SIZE]; } mem_node_t, *pmem_node_t; typedef struct _mem_block { mem_node_t *node_head; mem_node_t *node_tail; int node_cnt; /* node count */ struct _mem_block *next; } mem_block_t, *pmem_block_t; typedef struct _mem_pool { mem_block_t *block_head; mem_block_t *block_tail; mem_node_t *free_head; int block_cnt; /* block count */ int free_cnt; /* free node count; */ int base; int step; } mem_pool_t, *pmem_pool_t; static mem_pool_t mem_pool; /*************************************/ static int mem_block_init(int cnt, mem_block_t *block) { int size; mem_node_t *p; if (block == NULL) { return 0; } size = cnt * sizeof(mem_node_t); if ((p = (mem_node_t *) malloc(size)) == NULL) { fprintf(stderr, "mem_pool_init::malloc error/n"); return 0; } memset(p, 0, size); memset(block, 0, sizeof(mem_block_t)); block->node_cnt = cnt; block->node_head = p; block->node_tail = p + cnt - 1; for (p = block->node_head; p < block->node_tail; p++) p->next = (p + 1); p->next = NULL; return 1; } static int add_mem_block(int cnt) { mem_block_t *block; if ((block = (mem_block_t *) malloc(sizeof(mem_block_t))) == NULL) { fprintf(stderr, "add_mem_block::malloc error/n"); return 0; } memset(block, 0, sizeof(mem_block_t)); if (!mem_block_init(cnt, block)) { fprintf(stderr, "mem_pool_init::mem_block_init error/n"); return 0; } block->next = mem_pool.block_head; mem_pool.block_head = block; if (mem_pool.block_tail == NULL) { mem_pool.block_tail = block; } block->node_tail->next = mem_pool.free_head; mem_pool.free_head = block->node_head; mem_pool.free_cnt += cnt; mem_pool.block_cnt++; return 1; } int mem_pool_init() { memset(&mem_pool, 0, sizeof(mem_pool)); mem_pool.base = BASE_COUNT; mem_pool.step = STEP_COUNT; if (!add_mem_block(BASE_COUNT)) { fprintf(stderr, "mem_pool_init::add_mem_block error/n"); return 0; } return 1; } void mem_pool_destroy(void) { mem_block_t *prev, *cur; prev = NULL; cur = mem_pool.block_head; while (prev != NULL) { prev = cur; cur = cur->next; free(cur->node_head); free(prev); } memset(&mem_pool, 0, sizeof(mem_pool_t)); } /*************************************/ mem_node_t* mem_alloc() { //从free删除一个内存,返回这个分配地址 mem_node_t *p; if (mem_pool.free_head == NULL) { if (!add_mem_block(mem_pool.step)) { return NULL; } } p = mem_pool.free_head; mem_pool.free_head = p->next; mem_pool.free_cnt--; return p; } void mem_free(void *ptr) { //将ptr移到free表 if (ptr == NULL) { return; } ((mem_node_t *) ptr)->next = mem_pool.free_head; mem_pool.free_head = (mem_node_t *) ptr; mem_pool.free_cnt++; } #define ALLOC_COUNT 10 void alloc_test(char *ptr[]) { int i, j; for (i = 0; i < ALLOC_COUNT; i++) { if ((ptr[i] = (char*) mem_alloc()) == NULL) { fprintf(stderr, "mem_alloc error/n"); return; } for (j = 0; j < ALLOC_COUNT; j++) { ptr[i][j] = 'a' + j; } } for (i = 0; i < ALLOC_COUNT; i++) { for (j = 0; j < ALLOC_COUNT; j++) { printf("ptr[%d][%d]=%c ", i, j, ptr[i][j]); } } } int main() { char *ptr[ALLOC_COUNT]; if (!mem_pool_init()) { fprintf(stderr, "mem_pool_init error/n"); return 1; } alloc_test(ptr); mem_free(ptr[5]); mem_pool_destroy(); return 0; }
三,windows下文件操作
输出路径下所有文件目录树,递归创建文件目录
#include <cstdio> #include <cstring> #include <vector> #include <map> #include <windows.h> #include <fstream> #include <iostream> using namespace std; typedef struct _WIN32_FIND_DATA { //定义文件信息的数据结构 DWORD dwFileAttributes; //文件属性 FILETIME ftCreationTime; // 文件创建时间 FILETIME ftLastAccessTime; // 文件最后一次访问时间 FILETIME ftLastWriteTime; // 文件最后一次修改时间 DWORD nFileSizeHigh; // 文件长度高32位 DWORD nFileSizeLow; // 文件长度低32位 DWORD dwReserved0; // 系统保留 DWORD dwReserved1; // 系统保留 TCHAR cFileName[MAX_PATH]; // 长文件名 TCHAR cAlternateFileName[14]; // 8.3格式文件名 } FILE_INFO; bool File_Exist(TCHAR str[]) { //判断文件目录是否存在 HANDLE hFile; WIN32_FIND_DATAA wfd; if ((hFile != INVALID_HANDLE_VALUE ) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return 1; return 0; } multimap<string, string> MAP; //用于保存路径树的层次结构 multimap<string, string>::iterator it; void FindFile(char pFilePath[], string preFile) { //深搜文件目录并生成文件目录树,叶子节点为文件 WIN32_FIND_DATAA FindFileData; HANDLE hFind = INVALID_HANDLE_VALUE; char Dir[MAX_PATH]; strcpy(Dir, pFilePath); strncat(Dir, "\*", 3); hFind = FindFirstFile(Dir, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { printf("Can't find file "); return; } else { if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { MAP.insert(make_pair(preFile, FindFileData.cFileName)); } else if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && strcmp(FindFileData.cFileName, ".") != 0 && strcmp(FindFileData.cFileName, "..") != 0) { strcpy(Dir, pFilePath); strncat(Dir, "\", 2); strcat(Dir, FindFileData.cFileName); MAP.insert(make_pair(preFile, FindFileData.cFileName)); FindFile(Dir, FindFileData.cFileName); } while (FindNextFile(hFind, &FindFileData) != 0) { if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { //找到文件,到达叶子节点 MAP.insert(make_pair(preFile, FindFileData.cFileName)); } else if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && strcmp(FindFileData.cFileName, ".") != 0 && strcmp(FindFileData.cFileName, "..") != 0) { strcpy(Dir, pFilePath); strncat(Dir, "\", 2); strcat(Dir, FindFileData.cFileName); MAP.insert(make_pair(preFile, FindFileData.cFileName)); FindFile(Dir, FindFileData.cFileName); } } FindClose(hFind); } } void dfs(string Root, int cnt) { //按照文件目录树格式输出目录树 if (cnt > 4) return; multimap<string, string>::iterator i = MAP.find(Root); for (int i = 0; i < cnt - 1; i++) printf(" "); if (cnt) printf("|-->--->"); if (i == MAP.end()) { cout << Root << endl; return; } cout << "目录>" << Root << endl; for (; i != MAP.end() && i->first == Root; i++) dfs(i->second, cnt + 1); } void createFile(TCHAR * path) { //创建一个文件 CHAR *pBuffer; DWORD RSize; int fileSize = 0; TCHAR szPath[100]; strcpy(szPath, path); HANDLE hOpenFile = (HANDLE) CreateFileA(szPath, GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL); if (hOpenFile == INVALID_HANDLE_VALUE) { printf("Can't create file "); } fileSize = GetFileSize(hOpenFile, NULL); pBuffer = (CHAR *) malloc(fileSize); ReadFile(hOpenFile, pBuffer, fileSize, &RSize, NULL); free(pBuffer); } void createDirectory(TCHAR * path, int pos) { //创建多重目录,如果目录存在就进入,不存在就一直创建 TCHAR tmp_path[100]; while (pos < (int) strlen(path) && path[pos] != '\') pos++; strncpy(tmp_path, path, pos); if (!File_Exist(tmp_path)) { tmp_path[pos] = '