文件操作API

  1. 文件读写

    • fgetc fputc 按字符读写文件
    • fputs fgets 按行读写文件(读写配置)
    • fread fwrite 按块读文件(大文件迁移)
    • fprintf 格式化读写文件
  2. 文件控制

    • FILE *fopen(char *filename, char *type) 打开文件

      返回值:成功返回fp,失败返回NULL

      - r 只读 w只写 a 追加 - rb 二进制只读 wb 二进制只写 ab 二进制追加 - r+ 读写方式打开已存在文件 w+ 读写方式打开一个新的文件 a+ 读写打开文件追加 - rb+ 读写二进制 wb+ 建立二进制读写 ab+ 读写打开二进制追加

    • int fclose(fp) 关闭文件,成功返回0

    • ftell:指针离文件开头的距离,rewind:移动开头

    • fseek(fp,offset,origin) 以origin为起点,移动offset个字节 fseek(fp,10L,0) ->从开头10个字节

      • origin: SEEK_SET 0 (文件开头)
      • ​ SEEK_CUR 1 (当前位置)
      • ​ SEEK_END 2 (文件尾)

      - 清除文件缓冲区:int fflush(fp) int flushall()清除所有打开的文件

函数名字修饰

  • stdcall :参数从右到左压栈,函数自己负责清理栈,修饰以开头,有参数@Z结束,没有Z结束

    参数表的符号表示:
    X–void ,
    D–char,
    E–unsigned char,
    F–short,
    H–int,
    I–unsigned int,
    J–long,
    K–unsigned long,
    M–float,
    N–double,
    _N–bool,
    ….
    指针比较特殊,用PA表示指针,用PB表示const类型的指针。PA/PB+指针类型,如果相同类型的指针连续出现,用“0”表示,一个“0”表示一次重复,U表示结构类型,通常后面会跟上结构的类型名,“@@”表示结构类型名的结束。
    
  • 默认cdecl 函数名后加“@@YA” 从右到左压栈,参数栈由调用者维护(所以可以可变参数),调用者提供清理栈的代码

1
int __cdecl function(int a,int b) //明确指出C调用约定
  • fastcall 函数名后加“@@YI”,用ecx和edx两个寄存器传送前两个双字(DWORD)或更小的参数,其余的参数均按从右到左的顺序压栈;自己清理栈
  • thiscall C++的this,参数确定,this通过ecx,参数不定,this也通过堆栈

纯手工线程池

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

#define LL_ADD(item,list) do {              \
    item->prev = NULL;                      \
    item->next = list;                      \
    if(list != NULL) list->prev = item;     \
    list = item;                            \
}while(0)

#define LL_REMOVE(item,list) do {                           \
    if(item->prev != NULL) item->prev->next = item->next;   \
    if(item->next != NULL) item->next->prev = item->prev;   \
    if(list == item) list = item->next;                     \
    item->prev = item->next = NULL;                         \
}while(0)

//任务队列
struct NJOB{
    void(*func)(void *arg);
    void *user_data;
    struct NJOB *prev;
    struct NJOB *next;
};

//执行队列
struct NWORKER{
    struct NMANAGER *pool;
    pthread_t id;
    struct NWORKER *prev;
    struct NWORKER *next;
};

typedef struct NMANAGER{
    pthread_mutex_t mtx;
    pthread_cond_t cond;//条件变量

    struct NJOB *jobs;
    struct NWORKER *workers;
}nThreadPool;


void *thread_cb(void *arg){
    struct NWORKER * worker = (struct NWORKER *)arg;

    while(1){

        pthread_mutex_lock(&worker->pool->mtx);
        
        while (worker->pool->jobs == NULL)
        {
            pthread_cond_wait(&worker->pool->cond,&worker->pool->mtx);
        }

        //取一个job
        struct NJOB *job = worker->pool->jobs;
        if(job != NULL){
            LL_REMOVE(job, worker->pool->jobs);
        }

        pthread_mutex_unlock(&worker->pool->mtx);//应该放在这里
        
        job->func(job);
    }
}


//创建线程池
int nThreadPoolCreate(nThreadPool *pool,int numWorkers)
{
    //参数判断
    if(numWorkers < 1) numWorkers = 1;
    if(pool == NULL) return -1;

    memset(pool, 0, sizeof(nThreadPool));
    //mutex初始化
    pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->mtx, &blank_mutex, sizeof(pthread_mutex_t));
    //cond初始化
    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->cond, &blank_cond, sizeof(pthread_cond_t));

    //works
    int i = 0;
    for(i = 0; i < numWorkers; i++)
    {
        struct NWORKER *worker = (struct NWORKER *)malloc(sizeof(struct NWORKER ));
        if(worker == NULL)
        {
            perror("malloc:Null err");
            return -2;
        }
        memset(worker,0,sizeof(struct NWORKER));
        worker->pool = pool;
        pthread_create(&worker->id, NULL,thread_cb,worker);
        //线程添加到队列
        LL_ADD(worker,pool->workers);
    }
}

//销毁线程池
int nThreadPoolDestory(nThreadPool *pool)
{
    if(pool == NULL) return -1;
    struct NWORKER * tmp = pool->workers, *curr;
    while(tmp != NULL)
    {
        pthread_cancel(tmp->id); //杀死线程
        curr = tmp;
        tmp = tmp ->next;
        free(curr);
    }
    pthread_mutex_destroy(&pool->mtx);
    pthread_cond_destroy(&pool->cond);
}

//push任务
int nThreadPoolPushTask(nThreadPool *pool,struct NJOB *job)
{
    if(pool == NULL || job == NULL) return -1;
    pthread_mutex_lock(&pool->mtx);
    LL_ADD(job, pool->jobs);
    pthread_cond_signal(&pool->cond);//条件通知
    pthread_mutex_unlock(&pool->mtx);
}



#if 1
//测试程序
void jobs_cb(void *arg){
    struct NJOB * job = (struct NJOB *)arg;
    printf("I am %lu , data = %d\n",pthread_self(),*((int *)job->user_data));
    srand(time(0));
    usleep(rand()%100000);
    //usleep(1000);
}

int main()
{
    nThreadPool threadpool;
    nThreadPool *pool = &threadpool;

    nThreadPoolCreate(pool,10);

    int a[1000] = {0};
    struct NJOB job[1000];
    for(int i = 0; i<1000; ++i)
    {
        a[i] = i;
        job[i].func = jobs_cb;
        job[i].user_data = &a[i];
        job[i].prev = NULL;
        job[i].next = NULL;
        //添加任务
        nThreadPoolPushTask(pool,&job[i]);
    }
    sleep(5);

    nThreadPoolDestory(pool);
    return 0;
}
#endif