Linux系统编程(4)

分配数组

int *x, *y;
x = malloc(50*sizeof(int));
if(!x) {
    perror("malloc");
    return 1;
}

y = calloc(50, sizeof(int));
if (!y) {
    perror("calloc");
    return 1;
}

calloc会将所申请的内存全部填充0,malloc则不会。

调整内存分配的大小

#include 
void* realloc(void* ptr, size_t size);

 Linux系统编程(4)_第1张图片

 创建匿名内存映射

#include 

void * mmap(void* start, size_t length, int port, int flags, int fd, off_t offset);
int munmap(void* start, size_t length);
void* p;
p = mmap(NULL,     // 此处无关紧要
        512*1024,  // 512KB
        PROT_READ | PROT_WRITE,  // 可供读取和写入
        MAP_ANONYMOUS | MAP_PRIVATE, // 匿名与私有
        -1,   // fd 忽略
        0);   // offset 忽略
if (p == MAP_FAILED)
    perror("mmap")
else

-- 第一个参数start设定为NULL,表示匿名映射的起始地址由内核自行决定,也可以指定非NULL的值,只要能够对齐页面,这样会导致移植性早到破坏。

-- 为了让映射可读可写,一般设定prot参数为PROT_READ | PROT_WRITE。

-- flags参数设定为MAP_ANONYMOUS | MAP_PRIVATE,

-- 当MAP_ANONYMOUS设定时,参数fd和offset会被忽略。

相比malloc之后再设置为memset,calloc会更加方便。

 映射/dev/zero

void* p;
int fd;
// 打开/dev/zero以备读取和写入
fd = open("/dev/zero", O_RDWR);
if (fd < 0) {
    perror("open");
    return 1;
}
// /dev/zero 的【0, page size】映射
p = mmap(NULL,  //此时无关紧要
        getpagesize(),   // 映射一个页面
        PROT_READ | PROT_WRITE,  // 可写可读
        MAP_PRIVATE, // 私有映射
        fd,  // 映射 /dev/zero 
        0);

if (p == MAP_FAILED) {
    
        perror("mmap");
        if (close(fd))
            perror("close");
        return -1;
}

//关闭 /dev/zero 
if (close(fd))
    perror("close");

将字符串复制到堆栈

alloca()常用于临时复制一个字符串
//想要复制 "song"
char* dup;

dup = alloca(strlen(song)+1);
strcpy(dup, song);
//操作dup
return;
#define _GNU_SOURCE
#include 
char* strdupa(const char* s);
char* strndupa(const char* s, size_t n);

设定字节

#include 
void* memset(void* s, int c, size_t n);

Linux系统编程(4)_第2张图片

 比较字节

#include 
int memcmp(const void* s1, const void* s2, size_t n);

此函数会比较s1与s2的前n个字节,如果相等,返回0,如果s1s2,则返回.>0的值。

移动字节

#include 

void* memmove(void* dst, const void* src, size_t n);

 将src的前n个字节复制到dst,并返回dst.memmove()可以安全处理重叠区域。

#include 
void* memcpy(void* dst, const void* src, size_t n);

memcpy如同memmove,但是dst和src不可以重叠,如果重叠,则是未定义的。

#include 
void* memccpy(void* dst, const void* src, int c, size_t n);

memccpy()函数的行为如同memcpy(),但是如果此函数在src的前n个字节中发现了字节c,则停止复制,此函数会返回一个指针,指向dst中的c(如果找不到c,则指向NULL)之后的下一个字节。

最后使用mempcpy(),将数据复制到连续的内存位置。

#define _GNU_SOURCE
#include 

void* mempcpy(void* dst, const void* src, size_t n);

 mempcpy()函数的执行如同memcpy(),但是它会返回一个指针,指向复制的最后一个字节的下一个字节,如果有一组数据想要复制到连续的内存位置,这会很有用。

搜素字节

#include 
void* memchr(const void* s, int c, size_t n);

#define _GNU_SOURCE
#include 

void* memrchr(const void* s, int c, size_t n);

 Linux系统编程(4)_第3张图片

旋转字节

#define _GNU_SOURCE
#include 

void* memfrob(void* s, size_t n);

 信号列表

Linux系统编程(4)_第4张图片

Linux系统编程(4)_第5张图片 等待任何一个信号

 下面的程序会停在pause()处,直到收到一个信号,才会从pause()返回。

#include 
#include 
#include 
#include 

// SIGINT 处理程序
static void SIGINT_handler(int signo) {
    printf("Caught SIGINT!\n");
    exit(EXIT_SUCCESS);
}


int main(int argc, char** argv) {
    /**
     * 将SIGINT_handler注册为我们用于处理SIGINT的信号处理程序
    */
    if (signal(SIGINT, SIGINT_handler) == SIG_ERR) {
        fprintf(stderr, "Cannot handle SIGINT!\n");
        exit(EXIT_FAILURE);
    }
    for(;;) {
        pause();
    }
    return 0;
}
//编译:gcc -o test test.c
执行./test
然后输入Ctrl+C
#include 
#include 
#include 
#include 

// SIGINT 处理程序
static void SIGINT_handler(int signo) {
    if (signo == SIGINT) {
        printf("Caught SIGINT!\n");
    } else if (signo == SIGTERM) {
        printf("Caught SIGTERM!\n");
    } else {
        fprintf(stderr, "Unexpected signal!\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}


int main(int argc, char** argv) {
    /**
     * 将SIGINT_handler注册为我们用于处理SIGINT的信号处理程序
    */
    if (signal(SIGINT, SIGINT_handler) == SIG_ERR) {
        fprintf(stderr, "Cannot handle SIGINT!\n");
        exit(EXIT_FAILURE);
    }
    /**
     * 将SIGINT_handler注册为我们用于处理SIGTERM的信号处理程序
    */
    if (signal(SIGTERM, SIGINT_handler) == SIG_ERR) {
        fprintf(stderr, "Cannot handle SIGTERM!\n");
        exit(EXIT_FAILURE);
    }
    /**
     * SIGPROF 的行为重置为默认值
    */
    if (signal(SIGPROF, SIG_DFL) == SIG_ERR) {
        fprintf(stderr, "Cannot handle SIGPROF!\n");
        exit(EXIT_FAILURE);
    }

    /**
     * 忽略SIGHUP
    */
    if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
        fprintf(stderr, "Cannot handle SIGHUP!\n");
        exit(EXIT_FAILURE);
    }
    for(;;) {
        pause();
    }
    return 0;
}

发送一个信号

#include 
#include 

int kill(pid_t pid, int signo);

Linux系统编程(4)_第6张图片

 给自己发送一个信号

#include 
int raise(int signo);

给整个进程组传送一个信号

除了kill,可以使用

#include 
int killpg(int pgrp, int signo);

等效于
kill (-pgrp, signo);

保证可重入函数

Linux系统编程(4)_第7张图片

Linux系统编程(4)_第8张图片 

 信号集

#include 
int sigemptyset(sigset_t * set);
int sigfillset(sigset_t* set);
int sigaddset(sigset_t* set, int signo);
int sigdelset(sigset_t* set, int signo);
int sigismember(const sigset_t* set, int signo);

linux还提供以下非标准的函数:

#define _GNU_SOURCE
#include 

int sigisemptyset(sigset_t* set);
int sigorset(sigset_t * dest, sigset_t* left, sigset_t* right);
int sigandset(sigset_t* dest, sigset_t* left, sigset_t* right);

时间的数据结构

#include 
struct timeval {
    time_t tv_sec;    //seconds
    susecondes_t tv_usec;  //microsecondes
};


#include 
struct timespec {
    time_t tv_sec;   //seconds
    long tv_nsec;   //nanosecondes
};

Linux系统编程(4)_第9张图片

获取当前时间

#include 

time_t time(time_t* t);

time_t t;
printf("current time: %ld\n", (long)time(&t));
printf("the same value: %ld\n", (long)t);


#include 
int gettimeofday(struct timeval* tv, struct timezone* tz);

 

你可能感兴趣的:(linux)