美文网首页上嵌学习笔记
学习系统编程总结

学习系统编程总结

作者: 酸菜牛肉 | 来源:发表于2017-01-07 15:06 被阅读36次
    }2}YY@0DZ12E(B8$6~I`_QJ.png

    1,文件操作

    1.1普通文件操作:

    使用open函数创建函数

    
           #include <sys/types.h>
           #include <sys/stat.h>
           #include <fcntl.h>
    
           int open(const char *pathname, int flags);
           int open(const char *pathname, int flags, mode_t mode);
           int creat(const char *pathname, mode_t mode);
    

    函数功能:打开文件
    函数参数:pathname:待打开文件的路径,flags:打开文件的模式
    其中flags的参数有:
    O_RDONLY 只读模式,
    O_WRONLY 只写模式
    O_RDWR 读写模式
    O_CREAT 创建模式
    O_TRUNC
    O_EXCL
    flag中含有O_CREAT时才会使用到第三个参数mode
    S_IRWXU 用户的读写执行权限
    S_IRUSR 用户的读权限
    S_IWUSR 用户的写权限
    S_IXUSR 用户的执行权限
    S_IRWXG 用户组的读写执行权限
    返回值:文件的编号,为-1时,打开文件失败。

    读写文件

    使用read创建函数

     #include <unistd.h>
    
           ssize_t read(int fd, void *buf, size_t count);
    
    

    参数列表:
    fd:打开文件后的编号
    buf:将文件读取到指定的字符数组中
    count:可以读取文件的最大长度
    返回值:
    为0时,读到了到文件的末尾,为-1时,表示文件读取结束。。

    使用write写文件操作

     #include <unistd.h>
    
           ssize_t write(int fd, const void *buf, size_t count);
    

    参数列表:
    fd:打开文件后的文件编号
    buf:将指定的字符数组中的字符读入文件中
    count:可以读取长度,常用来填写read函数的返回值

    close关闭文件的函数

    #include <unistd.h>
    
           int close(int fd);
    

    参数:
    fd:文件的编号

    lseek文件定位函数

     #include <sys/types.h>
           #include <unistd.h>
    
           off_t lseek(int fd, off_t offset, int whence);
    
    

    参数列表:
    fd:文件编号
    offset:文件的位置
    whence:
    SEEK_SET
    SEEK_CUR
    SEEK_END

    stat获取文件的属性

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
           int stat(const char *path, struct stat *buf);
           int fstat(int fd, struct stat *buf);
           int lstat(const char *path, struct stat *buf);
    

    参数列表:
    path:文件的路径
    buf:文件信息的结构体
    可以使用man手册查看结构体的数据

    for example:文件的copy

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<unistd.h>
    
    #define BUFFER_SIZE 100
    
    int main(int argc,char *argv[])
    {
        if(argc != 3)
        {
            printf("usage:%s<src_file> <dst_file>\n",argv[0]);
            return 1;
        }   
        
        int src_fd = 0;
        int dst_fd = 0;
        int n = 0;
        char buf[BUFFER_SIZE] = {"\0"};
        char *src_file = argv[1];
        char *dst_file = argv[2];
        char cover_dir = '\0';
        char cover_filename[BUFFER_SIZE] = {'\0'};
        
        if(access(dst_file,F_OK) == 0)
        {
            printf("directorie is exist!!,,Do you want to cover, y or n:");
            scanf("%c",&cover_dir);
            switch(cover_dir)
            {
                case 'y':
                case 'Y':
                    {
                        //dst_fd = open(dst_file,O_WRONLY | O_TRUNC,S_IRUSR | S_IWUSR);
                        if((dst_fd = open(dst_file,O_WRONLY | O_TRUNC)) == -1)
                        {
                            perror("open dst error");
                            return -1;
                        }
                    }
                    break;
                case 'n':
                case 'N':
                    {
                        printf("Please resume load of filename:");
                        getchar();
                        scanf("%s",cover_filename);
                        if((dst_fd = open(cover_filename,O_WRONLY | O_TRUNC | O_CREAT,S_IRUSR | S_IWUSR)) == -1)
                        {
                            perror("open dst error\n");
                            return -1;
                        }   
                        break;                  
                    }
                    break;
                default:
                        printf("Please input again!!!\n");
                        return -1;
            }
        }
        else{
            if((dst_fd = open(dst_file,O_WRONLY | O_TRUNC | O_CREAT,S_IRUSR | S_IWUSR)) == -1)
            {
                                perror("open dst error");
                                return -1;
            }
        }
        if((src_fd = open(src_file,O_RDONLY)) == -1)
        {
            perror("open src error");
            return -1;
        }
        
        while((n = read(src_fd,buf,BUFFER_SIZE)) > 0)
        {
            write(dst_fd,buf,n);
        }
        
        close(src_fd);
        close(dst_fd);
        
        //1.open
    
        //2.1 read data form src_file
        //2.2 write data to dst_file
        
        //3.close       
        return 0;
    }
    
    • 读写函数必须在while中操作,是循环对字符串得到操作。

    1.2目录操作

    Linux下一切皆文件

    mkdir创建目录

     #include <sys/stat.h>
     #include <sys/types.h>
           int mkdir(const char *pathname, mode_t mode);
    

    参数列表:
    pathname:目录创建的路径
    mode:目录的模式
    返回值:为-1时,表示失败,为0时表示成功

    rmdir删除目录

      #include <unistd.h>
           int rmdir(const char *pathname);
    

    参数列表:
    目录的路径
    返回值:
    为0时,代表目录删除成功,为-1代表失败。

    opendir打开目录

     #include <sys/types.h>
           #include <dirent.h>
    
           DIR *opendir(const char *name);
    

    参数列表:
    name:目录的名称
    返回值:返回为NULL时,目录打开失败

    readdir读取目录

     #include <dirent.h>
              struct dirent *readdir(DIR *dirp);
              int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);//进行判断是否读取成功
    
    

    参数列表:
    dirp:文件类型和opendir返回值的类型一致
    返回值:返回一个结构体,其中d_name数据类型是文件的名称,

    closedir关闭程序

    #include <sys/types.h>
    #include <dirent.h>
           int closedir(DIR *dirp);
    

    参数列表:
    dirp:opendir打开文件的类型
    返回值:0是成功,1是失败

    #include<stdio.h>
    #include<sys/types.h>
    #include<dirent.h>
    //#include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    
    int main(int argc ,char *argv[])
    {
        if(argc != 2)
        {
            printf("usage:%s <dst_file>",argv[1]);
            return -1;
        }
        
        char *dst_file = argv[1];
        DIR *dirp = NULL;
        struct dirent *dp = NULL;
        struct stat *buf = NULL;
    
        if((dirp = opendir(dst_file)) == NULL){
            perror("opendir failed!!!");
            return -1;
        }
        while((dp = readdir(dirp)) != NULL){
            if(dp->d_name[0] == '.');
            else
                printf("%s\n",dp->d_name);
        }
         //int stat(const char *path, struct stat *buf);
         int n = stat(dst_file,buf);
         printf("%ld",buf->st_mode);
    
        closedir(dirp);
        
        return 0;
    }
    
    • readdir必须在while中执行,是逐条读取的

    多进程编程

    进程的创建和调度

    getpid/getppid进程ID号

    #include <sys/types.h>
           #include <unistd.h>
    
           pid_t getpid(void);
           pid_t getppid(void);
    

    参数:void
    返回值:
    分别为当前进程和父进程的进程号

    fork复制创建新的进程

    #include <unistd.h>
           pid_t fork(void);
    

    参数:void
    返回值:为0时代表子进程,>0时为父进程,通常用于区分父子进程的。

    exec函数族替换创建新进程

    #include <unistd.h>
    
           extern char **environ;
    
           int execl(const char *path, const char *arg, ...);
           int execlp(const char *file, const char *arg, ...);
           int execle(const char *path, const char *arg,
                      ..., char * const envp[]);
           int execv(const char *path, char *const argv[]);
           int execvp(const char *file, char *const argv[]);
           int execvpe(const char *file, char *const argv[],
                       char *const envp[]);
    

    参数列表:
    path:文件路径
    arg:参数列表,其后通常都会跟NULL

    • 例子:
    #include<stdio.h>
    #include<sys/types.h>
    #include<unistd.h>
    #include<string.h>
    #include<sys/stat.h>
    #include<pwd.h>
    #include <grp.h>
    
    #define DEBUG_MODE 1
    
    #define COM_MAX_LEN 128
    
    int main(int argc,char *argv[])
    {
        pid_t pid = 0;
        char command[COM_MAX_LEN] = {'\0'};
        int status = 0;
        char *delim = " ";
        char *str_command[2];
        struct passwd *pw = NULL;
        struct stat file_stat;
        
        memset(&file_stat, 0, sizeof(file_stat));
        
        while(1)
        {
            // 通过文件所有者ID获取文件所有者名称
            pw = getpwuid(file_stat.st_uid);
            printf("%s>", pw->pw_name);
            
            //printf(">>>>>>>>>");
            //uid_t     st_uid;     /* user ID of owner */
    
            
            fgets(command,COM_MAX_LEN,stdin);
            command[strlen(command)-1] = '\0';
            
            if(strcmp(command,".exit") == 0)
                return 0;
            
            str_command[0] = strtok(command,delim);
            str_command[1] = strtok(NULL,delim);
            //strcpy(str_command[],p);
        
            if((pid = fork()) == 0)
            {
            
                
                printf("in child peocess :%d\n",getpid());
                //利用exec函数将该子进程的执行指令替换
                execlp(str_command[0],str_command[0],str_command[1],NULL);
                //在path路劲中收索执行ls命令
                //2.在path路劲中搜索执行ls -l /命令
                //execlp("ls","ls","-l",NULL);
                return 0;
                
            }
            //防止僵尸进程的产生
            pid = wait(&status);
    #if DEBUG_MODE
            printf("in parent process child %d process exit code: \n",pid);
    #endif  
        
        }
        return 0;
    }
    

    wait/waitpid等待子进程退出

    #include <sys/types.h>
           #include <sys/wait.h>
    
           pid_t wait(int *status);
    
           pid_t waitpid(pid_t pid, int *status, int options);
    
    

    参数:
    status:
    返回值:返回子进程的ID
    作用:放置僵尸进程的产生

    信号

    一直异步通知机制
    常用的信号量有:
    SIGINT/SIGQUIT/SIGCLARM/SIGCHLD
    信号的三种处理方式:默认处理,忽略,自定义函数

    • 注意,信号处理不用做耗时操作

    signal/sigaction注册信号处理函数

     #include <signal.h>
    
           typedef void (*sighandler_t)(int);
           int sigaction(int signum, const struct sigaction *act,
                         struct sigaction *oldact);
    
           sighandler_t signal(int signum, sighandler_t handler);
           void ( *signal(int signum, void (*handler)(int)) ) (int);
    
    

    参数列表:
    signum:信号值
    handler:信号处理函数
    act:信号处理的一个结构体,里边存放的有信号李处的函数指针

    kill/组合键发送信号

     #include <sys/types.h>
           #include <signal.h>
    
           int kill(pid_t pid, int sig);
    
    

    参数列表:
    pid:进程号
    sig:信号
    返回值:
    发送成功为0;

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<signal.h>
    
    pid_t pid;
    
    void parent_process_sig_handler(int signo);
    
    void child_process_sig_handler(int signo);
    
    int main(int argc,char *argv[])
    {
        
        
        signal(SIGINT,parent_process_sig_handler);
        signal(SIGCHLD,parent_process_sig_handler);
        
        if((pid = fork()) == 0)
        {
            while(1)
            {
            
                signal(SIGINT,SIG_IGN);
                signal(SIGUSR1,child_process_sig_handler);
            
                int client_id = 0;
                
                client_id = rand()%100+1;
                printf("load data %dfrom data center..\n",client_id);
                sleep(1);
                printf("process data %ddown...\n",client_id);
            }
        }
        else if(pid > 0)
        {
            while(1);
        }
        else
        {
        
        }
    }
    
    void parent_process_sig_handler(int signo)
    {
        switch(signo)
        {
            case SIGCHLD:
            printf("SIGCHLD");
            wait(NULL);
            break;
            case SIGINT:
            kill(pid,SIGUSR1);
            break;
            default:
            break;
        }
    }
    
    void child_process_sig_handler(int signo)
    {
        if(signo == SIGUSR1)
        {
            printf("..%d\n",getpid());
            exit(0);
        }
    }
    
    

    进程间通信

    多线程编程

    线程的创建和调度

    pthread线程库
    pthread_create创建线程

     #include <pthread.h>
    
           int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                              void *(*start_routine) (void *), void *arg);
    
    

    参数列表:
    thread:线程ID的地址
    attr:NULL
    (*start_routine)(void *):线程函数指针,返回值也是一个函数指针类型
    arg:传递给函数指针的参数

    pthread_join等待获取线程的返回值

     #include <pthread.h>
    
           int pthread_join(pthread_t thread, void **retval);
    

    参数列表:
    thread:线程的ID
    retval:(void **)线程的返回值

    pthread_exit退出线程

    #include <pthread.h>
    
           void pthread_exit(void *retval);
    

    参数列表:线程结束时的返回值(void *);

    pthread_self获取线程自身ID

    #include <pthread.h>
    
           pthread_t pthread_self(void);
    

    参数列表:
    void
    返回值:线程自身的ID

    pthread_equal判断线程是否相等

    #include <pthread.h>
    
           int pthread_equal(pthread_t t1, pthread_t t2);
    

    参数列表:
    t1:线程1
    t2:线程2
    返回值:如果两个线程是相等的,则返回的是非0的数值
    否则,为0

    pthread_cancel取消指定线程

     #include <pthread.h>
    
           int pthread_cancel(pthread_t thread);
    
    

    参数列表:
    thread:线程ID
    返回值:如果成功返回值为0,失败则返回一个非零的数值

    #include<stdio.h>
    #include<pthread.h>
    #include<unistd.h>
    
    struct thread_arg
    {
        int thread_no;
        int lower;
        int upper;
    };
    
    struct thread_arg argument1,argument2;
    
    void *add_thread_func(void *arg);
    
    int main(int argc,char *argv[])
    {
        pthread_t thread_id1;
        pthread_t thread_id2;
        int *psum1 = NULL;
        int *psum2 = NULL;
        
        argument1.thread_no = 1;
        argument1.lower = 1;
        argument1.upper = 500;
        pthread_create(&thread_id1,NULL,add_thread_func,&argument1);
        
        argument2.thread_no = 2;
        argument2.lower = 501;
        argument2.upper = 1000;
        pthread_create(&thread_id2,NULL,add_thread_func,&argument2);
        
        pthread_join(thread_id1,(void **)&psum1);
        pthread_join(thread_id2,(void **)&psum2);
        
        printf("sum = %d\n",*psum1 + *psum2);
        
        free(psum1);
        free(psum2);
        
        return 0;
    }
    
    void *add_thread_func(void *arg)
    {
         struct thread_arg *p_arg = (struct thread_arg *)arg;
         int i = 0;
         int sum = 0;
         int *psum = (int *)malloc(sizeof(int));
         
         for(i = p_arg->lower;i < p_arg->upper+1;i++)
            sum += i;
         
         //printf("in thread no %d :sum = %ld\n",p_arg->thread_no,sum);
         *psum = sum;
         
         pthread_exit(psum);
    }
    

    线程并发要求

    同步:进程、线程中部分指令需要按照一定顺序执行
    异步:进程、线程的指令执行顺序无序
    互斥:对共享的资源操作只能有一个线程或进程
    竞争:对有限资源的共享产生的竞争关系
    死锁:互相等待资源
    饥饿:长时间无法获得资源

    线程间通信

    • 1,信息交换:使用多个线程都可见的内存区域
    • 2,线程互斥锁:保障有同一把锁保护的共享资源被多个线程互相访问

    pthread_mutex_t互斥锁

    互斥锁的类型

    pthread_mutex_init互斥锁初始化
    pthread_mutex_lock互斥锁的获取(加锁)
    pthread_mutex_unlock互斥锁的释放(解锁)

    #include<stdio.h>
    #include<pthread.h>
    #include<unistd.h>
    
    struct thread_arg
    {
        int thread_no;
        int lower;
        int upper;
    };
    
    struct thread_arg argument1,argument2;
    
    void *add_thread_func(void *arg);
    
    int main(int argc,char *argv[])
    {
        pthread_t thread_id1;
        pthread_t thread_id2;
        int *psum1 = NULL;
        int *psum2 = NULL;
        
        argument1.thread_no = 1;
        argument1.lower = 1;
        argument1.upper = 500;
        pthread_create(&thread_id1,NULL,add_thread_func,&argument1);
        
        argument2.thread_no = 2;
        argument2.lower = 501;
        argument2.upper = 1000;
        pthread_create(&thread_id2,NULL,add_thread_func,&argument2);
        
        pthread_join(thread_id1,(void **)&psum1);
        pthread_join(thread_id2,(void **)&psum2);
        
        printf("sum = %d\n",*psum1 + *psum2);
        
        free(psum1);
        free(psum2);
        
        return 0;
    }
    
    void *add_thread_func(void *arg)
    {
         struct thread_arg *p_arg = (struct thread_arg *)arg;
         int i = 0;
         int sum = 0;
         int *psum = (int *)malloc(sizeof(int));
         
         for(i = p_arg->lower;i < p_arg->upper+1;i++)
            sum += i;
         
         //printf("in thread no %d :sum = %ld\n",p_arg->thread_no,sum);
         *psum = sum;
         
         pthread_exit(psum);
    }
    
    • 线程信号量:解决多个线程在使用有限共享资源时的同步问题

    sem_t线程信号量

    线程信号量的数据类型

    sem_init信号量的初始化

    #include <semaphore.h>
    
           int sem_init(sem_t *sem, int pshared, unsigned int value);
    

    参数列表:
    sem:信号量的名称地址
    pshared:一般为0
    value:线程信号量的初始值
    返回值:成功为0,失败为-1

    sem_wait信号量获取(-1)

     #include <semaphore.h>
           int sem_wait(sem_t *sem);
    

    参数列表:
    sem:线程信号量的地址,通常需要加地址符
    返回值:成功为0,失败为-1

    sem_post信号量的释放(+1)

     #include <semaphore.h>
           int sem_post(sem_t *sem);
    

    参数列表:
    sem:线程信号量的地址,通常需要加地址符
    返回值:成功为0,失败为-1

    sem_destroy信号量的销毁

    #include <semaphore.h>
           int sem_destroy(sem_t *sem);
    

    参数列表:
    sem:线程信号量的地址,通常需要加地址符
    返回值:成功为0,失败为-1

    *例子:

    #include<stdio.h>
    #include<semaphore.h>
    #include<pthread.h>
    #include<signal.h>
    #include<unistd.h>
    
    sem_t sem;
    
    void *thread_func(void *arg);
    
    void sig_handler(int signo);
    
    int main(int argc,char *argv[])
    {
        pthread_t thread_id;
        
        //注册信号发送函数
        signal(SIGINT,sig_handler);
        
        //初始化信号量,值为0
        sem_init(&sem,0,0);
        
        pthread_create(&thread_id,NULL,thread_func,NULL);
        
        pthread_join(thread_id,NULL);
        
        printf("main....\n");
        
        //销毁信号量
        sem_destroy(&sem);
        
        return 0;
    }
    
    void *thread_func(void *arg)
    {
        while(1)
        {
            sem_wait(&sem);
            //信号量减一
            printf("thread func...\n");
            
            sleep(3);
        }
        
        pthread_exit(NULL);
    }
    
    void sig_handler(int signo)
    {
        if(signo == SIGINT)
        {
            sem_post(&sem);
            //信号量加一
        }
        
        pthread_exit(NULL);
    }
    

    进程的执行状态:新建、就绪、运行、阻塞、退出
    僵尸进程:自己进程退出之后,没有父进程wait
    孤儿进程:父进程在子进程之前退出,该子进程称为孤儿进程,进而被init进程收养

    相关文章

      网友评论

        本文标题:学习系统编程总结

        本文链接:https://www.haomeiwen.com/subject/jyotbttx.html