Linux系统编程【转】

转自:https://blog.csdn.net/majiakun1/article/details/8558308

一.Linux系统编程概论
1.1 系统编程基石
syscall:
libc:标准C库、系统调用封装、线程库、基本应用工具
gcc:

1.2 模块接口
API:应用程序编程接口,源代码级别,能通过编译,由标准C语言定义,libc来实现
ABI:应用程序二进制接口,二进制级别,能正常运行,关注调用约定、字节序、寄存器使用、系统调用、链接、二进制格式等,很难实现

1.3 错误处理
<stdio.h>
errno:
perror(const char *):

<string.h>
char * strerror (int errnum);
int strerror_r(int errnum, char *buf, size_t len);

二.文件管理

2.1 基本文件I/O
2.1.1 open系统调用
2.1.1.1 定义
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *name, int flags);
int open(const char *name, int flags, mode_t mode);

2.1.1.2 flags参数
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:读写
其它O_XXX:APPEND, ASYNC, CREAT, DIRECT, DIRECTORY, EXCL, LARGEFILE, NOCTTY, NOFOLLOW, NONBLOCK, SYNC, TRUNC

2.1.1.3 mode参数
文件权限,例如0777,仅当flags包含标志O_CREAT时需要提供,也是必须提供的

2.1.1.4 creat函数
int creat(const char *name, int mode);
等价于
open(name, O_WRONLY | O_CREAT | O_TRUNC, mode);

2.1.2 read系统调用
2.1.2.1 定义
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t len);

2.1.2.2 返回值 ret = read(fd, buf, len)
1)ret == len:调用正常,结果和预期一致
2)0< ret < len:信号打断了读取过程、读取中发生错误、已经到达文件末尾,处理的办法是继续读取剩余的字节,更新buf和len
3)ret == 0:已经到达文件末尾
4)ret == -1
    errno == EINTR:表示读入字节之前收到了一个信号,可以重新调用
    errno == EAGAIN:在非阻塞模式下发生,表示无数据可读
    other:发生了严重的错误
5)ret无返回值:阻塞了 

2.1.2.3 阻塞读取示例

while(len != 0 && (ret = read(fd, buf, len)))
{
    if(ret == -1)
    {
        if(errno == EINTR)
            continue;
        perror("read");
        break;
    }
    len -= ret;
    buf += ret;
}

2.1.2.4 非阻塞读取示例

char buf[BUFSIZ];
ssize_t nr;
do
{
    nr = read (fd, buf, BUFSIZ);
    if(nr == -1)
    {
        if(errno == EINTR)
            continue;
        if(errno == EAGAIN)
        {
            /* resubmit later */
        }
        else
        {
            perror("read");
            break;
        }
    }
    len -= ret;
    buf += ret;
}

2.1.2.5 pread:从指定的偏移量开始读取,不改变当前文件偏移量指针,可避免竞态的lseek调用
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t len, off_t pos);

2.1.3 write系统调用
2.1.3.1 定义
#include <unistd.h>
ssize_t write(int fd, const char *buf, size_t count);

2.1.3.2 示例代码
while(len != 0 && (ret = write(fd, buf, len)))
{
    if(ret == -1)
    {
        if(errno == EINTR)
            continue;
        perror("write");
        break;
    }
    len -= ret;
    buf += ret;
}

2.1.3.3 O_APPEND:适用于日志类型的应用

2.1.3.4 延迟写
内核设定了缓冲数据刷新的超时时间,由/proc/sys/vm/dirty_expire_centisecs定义

2.1.3.5 立刻写
1)int fsync(int fd):刷新文件fd的数据和元数据
2)int fdatasync(int fd):仅刷新文件fd的数据
3)void sync(void):刷新所有的缓冲数据,较耗时
4)O_SYNC,O_DSYNC,O_RSYNC:

2.1.3.6 O_DIRECT:忽略内核缓冲机制,最小化I/O管理,完全由用户处理请求长度,缓冲区对齐,文件偏移是扇区整数倍,例如数据库系统

2.1.3.7 pwrite:从指定的偏移量开始写,不改变当前文件偏移量指针,可避免竞态的lseek调用
#include <unistd.h>
ssize_t pwrite(int fd, void *buf, size_t len, off_t pos);

2.1.4 close系统调用
#include <unistd.h>
int close(int fd);

2.1.5 lseek系统调用
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t pos, int origin);
origin:SEEK_SET, SEEK_CUR, SEEK_END
pos = 0时
origin == SEEK_SET:文件偏移量指向文件起始位置
origin == SEEK_CUR:返回当前文件偏移量
origin == SEEK_END:文件偏移量指向文件末尾

2.1.6 truncate & ftruncate 系统调用
截短文件,成功调用返回文件长度
#include <sys/types.h>
#include <unistd.h>
int ftruncate(int fd, off_t len);
int truncate(const char *name, off_t len);

2.1.7 select & poll & epoll 系统调用
I/O多路复用,若有文件描述符准备好时通知我,没有就睡眠
2.1.7.1 select
1)定义
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
2)参数
n:fd_set中最大的fd + 1(不太合理,导致被poll取代)
3)返回值
成功时返回就绪的文件描述符数目
失败:
EBADF:某文件描述符非法
EINTR:等待时捕获了一个信号,可以重新发起调用
EINVAL:参数n是负数,或者时间timeout不合法
ENOMEM:没有足够的内存完成请求
4)示例程序
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

int main()
{
    struct timeval timeout;
    fd_set set;
    int ret;

    timeout.tv_sec = 3;
    timeout.tv_usec = 0;
    FD_ZERO(&set);
    FD_SET(STDIN_FILENO, &set);
    ret = select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout);

    if(ret < 0)
        perror("select");
    else
    {
        if(FD_ISSET(STDIN_FILENO, &set))
        {
            //read
        }
    }

    return 0;
}
5)可利用select实现sleep
6)pselect
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);
精确到纳秒,不修改timeout,设置阻塞的信号

2.1.7.2 poll
1)定义
#include <sys/poll.h>
struct pollfd
{
    int fd;            //文件描述符
    short events;    //监视的事件
    short revents;    //发生的事件
}
int poll(struct pollfd *fds, unsigned int nfds, int timeout);
2)事件
POLLIN、POLLRDNORM、POLLRDBAND、POLLPRI、POLLOUT、POLLWRNORM、POLLBAND、POLLMSG
3)ppoll
int ppoll(struct pollfd *fds, unsigned int nfds, int timeout, const sigset_t *sigmask);

2.1.7.3 epoll
解决select & poll性能问题,适合同时监视大量文件描述符,先初始化,然后增加、删除,最后等待,分离了三者
1)定义
#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

2.2 缓冲文件I/O
2.2.1 打开文件
FILE *fopen(const char *name, const char *mode);
FILE *fdopen(int fd, const char *mode);

2.2.2 关闭文件
int fclose(FILE *stream);
int fcloseall();

2.2.3 读文件
2.2.3.1 字节读
int fgetc(FILE *stream);
int ungetc(int c, FILE *stream);
2.2.3.2 行读取
int fgets(char *str, int size, FILE *stream):读取size-1个字节至str中,遇到换行符时,‘\n‘被存入str中
2.2.3.3 块读取
int fread(void *buf, size_t size, size_t nr, FILE *stream):从流stream中读入nr个元素,每个元素大小是size,返回读入的元素个数

2.2.4 写文件
2.2.4.1 字节写
int fputc(FILE *stream);
int unputc(int c, FILE *stream);
2.2.4.2 行写
int fputs(const char *str, FILE *stream);
2.2.4.3 块写
int fwrite(void *buf, size_t size, size_t nr, FILE *stream);

2.2.5 定位文件
int fseek(FILE *stream, long offset, int whence):移动文件指针到指定位置
int fsetpos(FILE *stream, fpos_t *pos):跨平台
int fgetpos(FILE *stream, fpos_t *pos)
int ftell(FILE *stream):返回当前文件位置
int rewind(FILE *stream):将文件指针置为初始位置

2.2.6 刷新文件
int fflush(FILE *stream):刷新用户缓冲区数据,不能刷新内核缓冲区数据
int fileno(FILE *stream):获取文件描述符fd,要先调用fflush

2.2.7 错误处理
int ferror(FILE *stream):测试是否有错误
int feof(FILE *stream):测试是否到达文件末尾
int clearerr(FILE *stream):清除错误标志

2.2.8 缓冲控制
int setvbuf(FILE *stream, char *buf, int mode, size_t size)
必须在紧邻fopen之后调用
mode:_IONBF(无缓冲),_IOLBF(行缓冲),_IOFBF(块缓冲)

2.2.9 文件锁
int flockfile(FILE *stream);
int funlockfile(FILE *stream);
int ftrylockfile(FILE *stream);
以上的流操作函数均是lock版,系统也提供了_unlock版

2.3 高级文件I/O
2.3.1 散列聚集I/O
#include <sys/uio.h>
ssize_t readv(int fd, const struct *iov, int count);
ssize_t writev(int fd, const struct *iov, int count);
单次向量I/O代替多次线性I/O,降低了系统调用次数,避免了竞态

2.3.2 直接文件I/O
1)定义
#include <sys/mman.h>
void *mmap(void *addr, size_t len, int port, int flags, int fd, off_t offset);
int munmap(void *addr, size_t len);
void * mremap (void *addr, size_t old_size,size_t new_size, unsigned long flags);
int mprotect (const void *addr, size_t len, int prot);
int msync (void *addr, size_t len, int flags);
int madvise (void *addr, size_t len, int advice);
2)addr:告诉内核最佳映射地址,不是强制,一般置为0,调用返回映射地址
3)port:权限,PORT_READ,PORT_WRITE,PORT_EXEC
4)flags
MAP_FIXED:addr是强制的
MAP_PRIVATE:映射区是私有的,写时拷贝
MAP_SHARED:映射区是共享的
5)页对齐:addr和len必须是页对齐的
long page_size = sysconf(_SC_PAGESIZE);  //最好选择
int page_size = getpagesize ( );
int page_size= PAGE_SIZE ;

2.3.3 文件I/O提示
1)posix fadvise
#include <fcntl.h>
int posix_fadvise (int fd, off_t offset, off_t len, int advice);

2)readahead
ssize_t readahead (int fd, off64_t offset, size_t count);

2.3.4 异步文件I/O
#include <aio.h>
/* asynchronous I/O control block */
struct aiocb
{
    int aio_filedes; /* file descriptor */
    int aio_lio_opcode; /* operation to perform */
    int aio_reqprio; /* request priority offset */
    volatile void *aio_buf; /* pointer to buffer */
    size_t aio_nbytes; /* length of operation */
    struct sigevent aio_sigevent; /* signal number and value */
    /* internal, private members follow... */
};
int aio_read (struct aiocb *aiocbp);
int aio_write (struct aiocb *aiocbp);
int aio_error (const struct aiocb *aiocbp);
int aio_return (struct aiocb *aiocbp);
int aio_cancel (int fd, struct aiocb *aiocbp);
int aio_fsync (int op, struct aiocb *aiocbp);
int aio_suspend (const struct aiocb * const cblist[], int n, const struct timespec *timeout);
Linux仅仅支持设置了O_DIRECT标志的异步操作

2.4 文件属性
2.4.1 inode:标识一个文件,在一个文件系统中是唯一的,既是linux内核虚拟对象,也是外存物理对象

2.4.2 获取文件属性
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int stat(const char *path, struct stat *buf);传入文件名
int fstat(int fd, struc stat *buf);传入文件描述符
int lstat(const char *path, struct stat *buf);返回链接文件本身

struct stat {
    dev_t st_dev;             /* ID of device containing file */
    ino_t st_ino;             /* inode number */
    mode_t st_mode;         /* permissions */
    nlink_t st_nlink;         /* number of hard links */
    uid_t st_uid;             /* user ID of owner */
    gid_t st_gid;             /* group ID of owner */
    dev_t st_rdev;             /* device ID (if special file) */
    off_t st_size;             /* total size in bytes */
    blksize_t st_blksize;     /* blocksize for filesystem I/O */
    blkcnt_t st_blocks;     /* number of blocks allocated */
    time_t st_atime;         /* last access time */
    time_t st_mtime;         /* last modification time */
    time_t st_ctime;         /* last status change time */
};

2.4.3 设置文件权限
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);

2.4.4 设置文件所有者
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);

2.4.5 扩展属性
#include <unistd.h>
#include <sys/types.h>
#include <sys/xattr.h>

1)命名空间:system,security,trusted,user

2)获取文件扩展属性
int getxattr(const char *path, const char *key, void *value, size_t size);
int fgetxattr(int fd, const char *key, void *value, size_t size);
int lgetxattr(const char *path, const char *key, void *value, size_t size);

3)设置文件扩展属性
int setxattr(const char *path, const char *key, void *value, size_t size, int flags);
int fsetxattr(int fd, const char *key, void *value, size_t size, int flags);
int lsetxattr(const char *path, const char *key, void *value, size_t size, int flags);

4)列举文件扩展属性
int listxattr(const char *path, char *list, size_t size);
int flistxattr(int fd, char *list, size_t size);
int llistxattr(const char *path, char *list, size_t size);

4)删除文件扩展属性
int removexattr(const char *path, char *key);
int fremovexattr(int fd, char *key);
int lremovexattr(const char *path, char *key);

2.5 目录管理
2.5.1 获取当前目录
#include <unistd.h>
char *getcwd(char *buf, size_t size);

2.5.2 更改目录
#include <unistd.h>
int chdir(const char *path);
int fchdir(int fd);

2.5.3 创建目录
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char *path, mode_t mode);

2.5.4 删除目录
#include <unistd.h>
int rmdir(const char *path);

2.5.5 读取目录
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dir);
int closedir(DIR *dir);

2.5.5 文件链接
#include <unistd.h>
1)硬链接
int link(const char *oldpath, const char *newpath);

2)符号链接
int symlink(const char *oldpath, const char *newpath);

3)解除链接
int unlink(const char *path);

2.5.6 文件复制移动删除
1)复制:无系统级支持,自己实现
2)移动
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
3)删除
#include <stdio.h>
int remove(const char *path);

2.6 设备文件
2.6.1 特殊设备文件
1) /dev/null:空设备,忽略所有写请求,读请求返回EOF
2) /dev/zero:零设备,忽略所有写请求,读请求返回0
3) /dev/full:满设备,写请求返回ENOSPC,读请求返回0
4) /dev/urandom:随机数生成设备,优于/dev/random

2.6.2 设备控制
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
int ioctl(int fd, int request, ...);

2.7 监视文件
#include <inotify.h>
inotify,监视文件被创建、打开、读取、写入、删除等操作

2.7.1 初始化
int inotify_init();

2.7.2 增加监视
int inotify_add_watch(int fd, const char *path, uint32_t mask);

2.7.3 inotify 事件
struct inotify_event {
    int wd;             /* watch descriptor */
    uint32_t mask;         /* mask of events */
    uint32_t cookie;     /* unique cookie */
    uint32_t len;         /* size of ’name’ field */
    char name[];         /* null-terminated name */
};

2.7.4 读取inotify 事件:read

2.7.5 删除inotify 事件
int inotify_rm_watch (int fd, uint32_t wd);

2.7.6 退出inotify:close

三.进程管理
进程创建fork和加载exec分离,是仅次于文件的基本抽象概念

3.1 获取进程ID
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
1)PID在某个时刻是唯一的
2)进程0:idle进程,是所有其他进程的祖先,在系统初始化时由kernel自身从无到有创建。(过程集中在start_kernel函数内),数据成员大部分是静态定义的,即由预先定义好的(如上)INIT_TASK, INIT_MM等宏初始化。
3)进程1:init进程,由idle进程调用kernel_thread创建的

3.2 进程创建fork
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);

pid_t pid;
pid = fork();
if(pid == -1)
{
    perror("fork");
}
else if(pid == 0)
{
    //父进程代码
}
else
{
    //子进程代码
    if( execlp("gedit", "gedit", "001.txt", NULL) == -1)
    {
        perror("execl");
        exit(EXIT_FAILURE);
    }
}

3.3 进程加载exec
#include <unistd.h>
int execl(const char *path, const char *arg, ...):加载指定路径的程序,参数列表必须以NULL结束
int execlp(const char *path, const char *arg, ...):在PATH环境变量中查找程序
int execle(const char *path, const char *arg, ..., char * const envp[]):提供给新进程环境变量
int execv(const char *path, char * const argv[]);
int execvp(const char *path, char * const argv[]);
int execve(const char *path, char * const argv[], char * const envp[]);
l表示以列表方式提供参数,v表示以数组方式提供参数,p表示在PATH环境变量中查找程序,e表示提供给新进程环境变量

3.4 进程终止exit
#include <stdlib.h>
void exit(int status);
EXIT_SUCCESS表示成功,EXIT_FAILURE表示失败
1)_exit
#include <unistd.h>
void _exit(int status);

2)at_exit
#include <stdlib.h>
int at_exit(void (*function)(void ));

3)SIGCHLD:当进程终止时,内核会向其父进程发送信号SIGCHLD

4)wait
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
返回已终止子进程PID,返回-1表示出错

5)waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid (pid_t pid, int *status, int options);
功能更强大

6)system
#include <stdlib.h>
int systme(const char *command);
创建并等待新进程

int my_system (const char *cmd)
{
    int status;
    pid_t pid;
    pid = fork ( );
    if (pid == -1)
        return -1;
    else if (pid == 0) {
        const char *argv[4];
        argv[0] = ”sh”;
        argv[1] = ”-c”;
        argv[2] = cmd;
        argv[3] = NULL;
        execv (”/bin/sh”, argv);
        exit (-1);
    }
    if (waitpid (pid, &status, 0) == -1)
        return -1;
    else if (WIFEXITED (status))
        return WEXITSTATUS (status);
    return -1;
}

3.5 进程权限控制
3.5.1 用户ID
1) 实际用户ID:登陆进程使用的ID
2) 有效用户ID:检查进程权限过程中使用的ID
3) 保存设置用户ID:执行suid前的有效用户ID
4) 文件系统用户ID:

3.5.2 设置用户ID
#include <unistd.h>
#include <sys/types.h>
int setuid(uid_t uid);
int setgid(gid_t gid);
int seteuid(uid_t uid);
int setegid(gid_t gid);
设置当前进程的有效用户ID

3.5.3 获取用户ID
#include <unistd.h>
#include <sys/types.h>
int getuid();
int getgid();
int geteuid();
int getegid();

3.5.4 会话
登陆进程会为新用户创建会话,会话首进程(shell)pid作为会话ID,便于作业控制,可以发信号终止会话首进程的所有子进程
#include <unistd.h>
1) 创建一个会话: pid_t setsid(void);
2) 获取会话ID: pid_t getsid (pid_t pid);
3) 设置进程组ID: int setpgid (pid_t pid, pid_t pgid);

3.6 守护进程
#include <unistd.h>
int daemon(int nochdir, int noclose);

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fs.h>
int main (void)
{
    pid_t pid;
    int i;

    pid = fork( );  /* create new process */
    if (pid == -1)
        return -1;
    else if (pid != 0)
        exit (EXIT_SUCCESS);

    if (setsid ( ) == -1)  /* create new session and process group */
        return -1;

    if (chdir (”/”) == -1)  /* set the working directory to the root directory */
        return -1;

    for (i = 0; i < NR_OPEN; i++)  /* close all open files--NR_OPEN is overkill,but works */
        close (i);

    /* redirect fd’s 0,1,2 to /dev/null */
    open (”/dev/null”, O_RDWR); /* stdin */
    dup (0); /* stdout */
    dup (0); /* stderror */

    /* do its daemon thing... */

    return 0;
}

3.7 进程调度
3.7.1 让出处理器
#include <sched.h>
int sched_yield(void);

3.7.2 进程优先级
#include <unistd.h>
int nice(int inc);
在当前优先级基础上加inc,只有拥有CAP_SYS_NICE能力才能使用负值inc增加优先级,否则只能降低优先级

#include <sys/time.h>
#include <sys/resource.h>
int getpriority (int which, int who);
int setpriority (int which, int who, int prio);

3.7.3 处理器亲和度
#include <sched.h>
typedef struct cpu_set_t;
size_t CPU_SETSIZE;
void CPU_SET (unsigned long cpu, cpu_set_t *set);
void CPU_CLR (unsigned long cpu, cpu_set_t *set);
int CPU_ISSET (unsigned long cpu, cpu_set_t *set);
void CPU_ZERO (cpu_set_t *set);
int sched_setaffinity (pid_t pid, size_t setsize,const cpu_set_t *set);
int sched_getaffinity (pid_t pid, size_t setsize,const cpu_set_t *set);

3.7.4 进程调度策略
#include <sched.h>
struct sched_param {
    /* ... */
    int sched_priority;
    /* ... */
};
int sched_getscheduler (pid_t pid);
int sched_setscheduler (pid_t pid, int policy,const struct sched_param *sp);
int sched_getparam (pid_t pid, struct sched_param *sp);
int sched_setparam (pid_t pid, const struct sched_param *sp);
int sched_rr_get_interval (pid_t pid, struct timespec *tp);
SCHED_FIFO:先进先出
SCHED_RR:轮转
SCHED_OTHER:普通

3.7.5 资源限制
#include <sys/time.h>
#include <sys/resource.h>
struct rlimit {
    rlim_t rlim_cur; /* soft limit */
    rlim_t rlim_max; /* hard limit */
};
int getrlimit (int resource, struct rlimit *rlim);
int setrlimit (int resource, const struct rlimit *rlim);
RLIMIT AS,CORE,CPU,DATA,FSIZE,LOCKS,MEMLOCK,MSGQUEUE,NICE,NOFILE,NPROC,RSS,RTPRIO,SIGPENDING,STACK

四.内存管理
4.1 基本存储/释放
4.1.1 malloc
#include <stdlib.h>
void *malloc(size_t size);
成功会返回指向size大小内存区域的首指针,错误返回NULL,设置errno为ENOMEM

4.1.2 calloc
#include <stdlib.h>
void *calloc(size_t nr, size_t size);
分配数组,会用0初始化

void *xmalloc0(size_t size)
{
    void *p = NULL;
    p = calloc(1, size);
    if(p == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    return p;
}

4.1.3 realloc
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
重新分配,可改变已分配内存区域的大小,主要用途是变小

4.1.4 free
#include <stdlib.h>
void free(void *ptr);
ptr必须是malloc/calloc/realloc的返回值

4.2 字节对齐
#include <stdlib.h>
int posix_memalign (void **memptr,size_t alignment,size_t size);
成功时返回size字节的动态内存,且以alignment,alignment必须是2的幂

4.3 匿名映射
void *p;
p = mmap (NULL, 512 * 1024, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
    perror (”mmap”);
else
    /* p points at 512 KB of anonymous memory... */
...
int ret;
ret = munmap(p, 512 * 1024);
if(ret)
    perror("munmap");
适合大内存区域分配

4.4 设置内存分配参数
#include <malloc.h>
int mallopt (int param, int value);
size_t malloc_usable_size (void *ptr);
int malloc_trim (size_t padding);

4.5 调试内存分配
#include <malloc.h>
struct mallinfo mallinfo (void);
/* all sizes in bytes */
struct mallinfo {
    int arena;
    int ordblks;
    int smblks;
    int hblks;
    int hblkhd;
    int usmblks;
    int fsmblks;
    int uordblks;
    int fordblks;
    int keepcost;
};

#include <malloc.h>
void malloc_stats (void);

4.6 栈分配&变长数组
#include <alloca.h>
void * alloca (size_t size);

原文地址:https://www.cnblogs.com/sky-heaven/p/9485996.html

时间: 2024-10-11 01:34:40

Linux系统编程【转】的相关文章

LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程需要做的什么事情,所以特定看了UNIX环境编程和LINUX系统编程这2本书 重新梳理下整个要点. 内容: 一般而言: 如果程序类似于下面的情况: if((pid=fork())==0) { dochildtthing(); exit(0); } else if(pid>0) { dofathertt

Linux系统编程-setitimer函数

功能:linux系统编程中,setitimer是一个经常被使用的函数,可用来实现延时和定时的功能. 头文件:sys/time.h 函数原型: int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value); 参数含义: 1.which参数用来设置定时器类型,可选的值为 (1)ITIMER_REAL : 设置定时器以系统真实所花费的时间来计时,运行指定时间后发送SIGALRM信号. (

Linux系统编程笔记

写在开篇:出于对未来职业规划的考虑(其实还是一团糟),制定了一个基本的学习方向,那就是从系统编程学习API慢慢的深入内核,这是一个比较成熟的学习路线.所以从本篇开始,在这段时间会陆续记录Linux系统编程的学习笔记,除了供学习之余复习只用,同时也期望能记录初入职场摸爬滚打的第一个3年. 第一章 文件I/O 文件访问的基本调用一般是 read()和write(),但是在访问文件之前,要做的是一项很重要的工作就是:打开,没错!通过调用 open()或create()实现 #include <sys/

Linux系统编程@进程通信(一)

进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统的一个分支) POSIX进程间通信(POSIX:可移植操作系统接口,为了提高UNIX环境下应用程序的可移植性.很多其他系统也支持POSIX标准(如:DEC OpenVMS和Windows).) 现在Linux使用的进程间通信方式包括: 管道(pipe).有名管道(FIFO) 信号(signal) 消

linux系统编程之管道(一):匿名管道(pipe)

原文地址:http://www.cnblogs.com/mickole/p/3192210.html 一,什么是管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 数据的读

Linux系统编程之访问文件夹及其文件属性

1. 文件夹操作:opendir, readdir, closedir 2. 文件属性:lstat 3. 实现功能:获取指定文件夹下所有的文件(使用递归),因此就能计算所有文件大小之类的啦... 代码示例如下: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/stat

linux系统编程之信号(四)

今天继续探讨信号相关的东东,话不多说,正入正题: 信号在内核中的表示: 下面用图来进一步描述这种信号从产生到递达之间的状态(信号阻塞与未诀): 那是怎么来决定的呢?下面慢慢来举例分解: 所以,通过这些图,可以描述信号从产生到递达的一个过程,上面的理解起来可能有点难,下面会用代码来进一步阐述,在进行实验之前,还需了解一些函数的使用,这些函数在实验中都会被用到,也就是信号集操作函数. 信号集操作函数: 其中解释一下sigset_t,百度百科解释为: 而这个函数的意义就是将这64位清0 这个函数的意义

Linux系统编程札记:进程通信(一) &nbsp; &nbsp;

进程简单来讲就是一个程序的一次执行,这里说的进程一般都指的是运行在用户态的进程,而处于用户态的不同进程之间是彼此相互隔离的,它们必须通过某种方式来进行通信,具体理由如下: (1)数据传输:有时候一个进程需要将它的数据发送给另一个进程. (2)资源共享:有时候多个进程之间需要共享同样的资源. (3)通知事件:有时候一个进程需要向另一个或一组进程发送消息,通知它们发生了某个事件. (4)进程控制:有些进程希望能够完全控制另一个进程的执行,此时控制进程希望能够拦截另一进程的所有操作,并能够及时知道它的

嵌入式 Linux系统编程(一)——文件IO

嵌入式 Linux系统编程(一)--文件IO 一.文件IO概念 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作.不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出.它以文件标识符(整型)作为文件唯一性的判断依据.这种操作不是ASCI标准的,与系统有关,移植有一定的问题.而带缓存的是在不带缓存的基础之上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ASCI标准,称为标准IO库.不带缓存的方式频繁进行用户态 和内核

嵌入式 Linux系统编程(二)——文件描述符控制函数fcntl

嵌入式 Linux系统编程(二)--文件描述符控制函数fcntl 由于fcntl函数实在过于灵活和复杂,本文将fcntl函数从文件IO中单独列出来,便于详细解读.函数原型如下: #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ ); fcntl函数用于控制操作文件描述符fd,对文件描述符的控制操作由cmd控制命令来控制,arg参数为可选参数,是否需要arg参数取决于控制命令