• 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中,遇到换行符时,'
    '被存入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);
  • 相关阅读:
    2.如何安装vmvare tools
    1.如何安装ubuntu
    14.如何读取配置文件的键值对
    android app调试没问题,但打包签名的apk,运行时出现闪退怎么办?
    如何使用jedis进行发布订阅
    如何使用mybatis对mysql数据库进行操作,batis的增删改查
    如何解释json的字符串
    redis可视化工具redisClient
    如何连接远程redis,并且选择某个库进行操作
    理解RESTful架构
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/9485996.html
Copyright © 2020-2023  润新知