Linux系统编程(4)

编程入门 行业动态 更新时间:2024-10-24 10:24:00

Linux<a href=https://www.elefans.com/category/jswz/34/1770742.html style=系统编程(4)"/>

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 <stdlib.h>
void* realloc(void* ptr, size_t size);

 

 创建匿名内存映射

#include <sys/mman.h>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,  // 512KBPROT_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 <string.h>
char* strdupa(const char* s);
char* strndupa(const char* s, size_t n);

设定字节

#include <string.h>
void* memset(void* s, int c, size_t n);

 比较字节

#include <string.h>
int memcmp(const void* s1, const void* s2, size_t n);

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

移动字节

#include <string.h>void* memmove(void* dst, const void* src, size_t n);

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

#include <string.h>
void* memcpy(void* dst, const void* src, size_t n);

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

#include <string.h>
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 <string.h>void* mempcpy(void* dst, const void* src, size_t n);

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

搜素字节

#include <string.h>
void* memchr(const void* s, int c, size_t n);#define _GNU_SOURCE
#include <string.h>void* memrchr(const void* s, int c, size_t n);

 

旋转字节

#define _GNU_SOURCE
#include <string.h>void* memfrob(void* s, size_t n);

 信号列表

 等待任何一个信号

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

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>// 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 <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>// 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 <sys/types.h>
#include <signal.h>int kill(pid_t pid, int signo);

 给自己发送一个信号

#include <signal.h>
int raise(int signo);

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

除了kill,可以使用

#include <signal.h>
int killpg(int pgrp, int signo);等效于
kill (-pgrp, signo);

保证可重入函数

 

 信号集

#include <signal.h>
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 <signal.h>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 <sys/time.h>
struct timeval {time_t tv_sec;    //secondssusecondes_t tv_usec;  //microsecondes
};#include <time.h>
struct timespec {time_t tv_sec;   //secondslong tv_nsec;   //nanosecondes
};

获取当前时间

#include <time.h>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 <sys/time.h>
int gettimeofday(struct timeval* tv, struct timezone* tz);

 

更多推荐

Linux系统编程(4)

本文发布于:2023-12-04 07:15:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1660153.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:系统   Linux

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!