系统编程

作者: 尘随风 | 来源:发表于2017-01-09 09:00 被阅读29次

    文件操作

    打开文件

    使用open函数和create函数打开和创建文件

    c

    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     打开的模式:
    
          O_RDONLY      只读模式
          O_WRONLY      只写模式
          O_RWONLY      读写模式
          O_CREAT       如果文件不存在,按照mode参数指定的权限创建文件
          O_TRUNC       如果打开的文件已经存在,并且指定了可写标志,则删除文件内容重新写入
    * 返回值: -1表示打开失败
    
    ##读写文件
    >使用read函数跟write函数对文件进行读写操作
    
    ```C
    #include <unistd.h>
    ssize_t read(int fd, void *buf, size_t count);
    ssize_t write(int fd, const void *buf, size_t count);
    

    函数参数

    • fd: 要进行读写操作的文件描述符
    • buf: 要写入文件内容或读出文件内容的内存地址
    • count: 要读写的字节数

    注意:必须要提供一个足够大的缓冲区,既buf的长度要大于或者等于count,成功则返回所读取或写入的字节数目,否则返回-1。

    关闭文件

    使用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:文件指针移动距离

    注意:指针不要超出文件范围

    例:用文件的的读写实现文件内容的复制

    #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_sile>\n",argv[0]);
            return 1;
        }
        int src_fd = 0;
        int dst_fd = 0;
        int n = 0;
        char ch;
        char buf[BUFFER_SIZE] = {'\0'};
        if((src_fd = open(argv[1],O_RDONLY)) == -1)
        {
            perror("open error");
            return 1;
        }
        while(1)
        {
            if(access(argv[2],F_OK) == 0)
            {
                printf("文件已存在,是否覆盖?y or n?\n");
                scanf("%c",&ch);
                if(ch == 'y')
                {
                    break;
                }
                printf("请重新输入目的文件名:\n");
                scanf("%s",argv[2]);
                getchar();
            }
            else
                break;
        }
        if((dst_fd = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC,S_IRUSR | S_IWUSR)) == -1)
        {
            perror("open dst error");
            return 1;
        }
        while((n = read(src_fd,buf,BUFFER_SIZE)) > 0)
        {
            write(dst_fd,buf,n);
        }
        close(src_fd);
        close(dst_fd);
        return 0;
    }
    

    目录操作

    • 创建目录:mkdir
    • 删除目录:rmdir
    • 打开目录:opendir
    • 关闭目录:closedir
    • 读取目录项信息:readdir

    打开目录要用DIR类型的指针,例:

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<dirent.h>
    
    int main(int argc,char *argv[])
    {
        DIR *dirp = NULL;
        struct dirent *dp = NULL;
        if((dirp = opendir(".")) == NULL)
        {
            perror("open faild");
            return 1;
        }
        while((dp = readdir(dirp)) != NULL)
        {
            if(dp->d_name[0] != '.')
                printf("%s\n",dp->d_name);
        }
        closedir(dirp);
        return 0;
    }
    

    进程操作

    创建进程

    fork()

    创建一个子进程完全copy父进程的内容,并且子进程从fork()开始执行,
    子进程的返回值(fork())为0;
    父进程的返回值是子进程的进程号(pid);

    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[]);
    
    • file:文件名
    • arg:argv含有argv[0],argv[1]......
      替换当前进程后续执行的内容

    清除僵死进程

    用wait()或waitpid()函数清楚僵死进程

    获得进程号

    • getpid():获得当前进程号
    • getppid():获得父进程的进程号
    #include <sys/types.h>
    #include <sys/wait.h>
    pid_t wait(int *status);
    pid_t waitpid(pid_t pid, int *status, int options);
    
    • int 型的 status是用来存放子进程结束的状态值,如果要打印出来需要使用WEXITSTATUS(status);

    • 如果不关心返回的状态值,可以直接用wait(NULL);

    • pid:需要wait的进程号

    • 例:用fork()创建进程并用exec()替换子进程

    #include<stdio.h>
    #include<unistd.h>
    #include<string.h>
    #include<pwd.h>
    
    #define MAX_CMD_LEN 100
    void strqie(char *str);
    
    int main(int argc,char *argv[])
    {
        pid_t pid;
        char command[MAX_CMD_LEN] = {'\0'};
        char tips[200] = {'\0'};
        char cwd[100] = {'\0'};
        
        while(1)
        {
            //printf(">>>");
            getcwd(cwd, 100);
            sprintf(tips,"%s:%s$",getpwuid(getuid())->pw_name, cwd);
            printf("%s",tips);
            fgets(command, MAX_CMD_LEN, stdin);
            command[strlen(command) - 1] = '\0';    //  替换'\n'
            if(strncmp(command, ".exit",5) == 0)
                break;
            if((pid = fork()) == 0)
            {
                printf("prepare to run %s...\n", command);
                if(execlp(command,command,NULL) == -1);
                {
                    printf("run command error\n");
                    return 1;
                }
            }
            else if(pid > 0)
            {
                wait(NULL);
            }
            else
            {
                
            }
        }
        return 0;
    }
    
    void strqie(char *str)
    {
        char *base = str;
        char tmp[MAX_CMD_LEN] = {'\0'};
        while(*str != '\0')
        {
            if(*str == ' ')
            {
                strncpy(tmp, base, str-base);
                printf("arg : %s\n", tmp);
                base = str + 1;
                str++;
            }
            else
            {
                str++;
            }
        }
    }
    

    注意:

    • fork()是拷贝父进程的所有内容并创建子进程,
    • exec族函数是无法创建新进程的,只能进行替换
    • 父进程先于子进程退出,子进程会成为孤儿进程,并被init进程收养

    线程操作

    创建线程

    #include<pthread.h>
    线程函数:void *thread_func(void *arg);
    pthread_t thread_id;
    pthread_create(&thread_id,NULL,线程函数名,NULL);
    pthread_join(&thread_id,NULL);
    在线程函数内部以pthread_exit(NULL);结束
    
    • 获取线程自身的线程ID:pthread_self
    • 判断是否是同一个线程:pthread_equal
      int pthread_equal(pthread_t t1, pthread_t t2);
    • 取消指定线程:pthread_cancel
      int pthread_cancel(pthread_t thread);

    使用锁

    #include<pthread.h>
    pthread_mutex_t metex;      ----->创建锁
    pthread_mutex_init(&mutex,NULL);----->初始化锁  //不用赋值
    pthread_mutex_lock(&mutex); ----->获取锁
    pthread_mutex_unlock(&mutex);   ----->释放锁
    注意:锁的获取和释放必须成对出现
    

    使用信号量

    #include<semaphore.h>
    sem_t sem;  --------->创建信号量
    sem_init(&sem,0 , 0);----->初始化信号量为0
    sem_wait(&sem); --------->信号量减一,如果信号量小于0,则阻塞
    sem_post(&sem); --------->信号量加一,如果信号量等于0,则唤醒一个等待的线程
    sem_destroy(&sem);------->销毁信号量
    

    处理信号

    signal(SIGINT,自定义函数名);自定义函数:void sig_handler(int signo){};

    • pause():等待信号输入
    • kill(进程号(pid),信号);向某个进程发送信号

    例:生产者与消费者问题

    #ifndef __SQ_QUEUE_H__
    #define __SQ_QUEUE_H__
    typedef struct data
    {
        int data;
        struct data *next;
    }DATA;
    
    typedef struct node
    {
        DATA *front;
        DATA *rear;
    }NODE;
    
    
    NODE* create_duilie(NODE *queue);
    
    void add_duilie(NODE *queue,int n);
    
    int len_duilie(NODE *queue);
    
    int del_duilie(NODE *queue);
    
    #endif
    //*************************************
    #include"link_queue.h"
    #include<stdlib.h>
    
    
    //创建队列
    NODE* create_duilie(NODE *queue)
    {
        DATA *p = (DATA *)malloc(sizeof(DATA));
        p->next == NULL;
        queue = (NODE *)malloc(sizeof(NODE));
        
        queue->front = p;
        queue->rear = p;
        p = NULL;
        return;
    }
    //尾插法插入
    void add_duilie(NODE *queue,int n)
    {
        DATA *p = (DATA *)malloc(sizeof(DATA));
        p->data = n;
        
        p->next = queue->rear->next;
        queue->rear->next = p;
        queue->rear = p;
        //p = NULL;
        return;
    }
    //计算队列个数
    int len_duilie(NODE *queue)
    {
        int len = 0;
        DATA *p = queue->front;
        while(p->next != NULL)
        {
            len++;
            p = p->next;
        }
        return len;
    }
    //头删法删除
    int del_duilie(NODE *queue)
    {
        int n = 0;
        DATA *p = queue->front->next;
        n = p->data;
        queue->front->next = p->next;
        free(p);
        p = NULL;
        if(queue->front->next == NULL)
            queue->rear = queue->front;
        return n;
    }
    //*****************************
    #include<stdio.h>
    #include"link_queue.h"
    #include<pthread.h>
    #include<time.h>
    #include<semaphore.h>
    
    
    sem_t sem1;
    sem_t sem2;
    pthread_mutex_t mutex;
    
    NODE *queue;
    
    int num = 0;
    void *func1(void *arg);
    
    void *func2(void *arg);
    
    void *func3(void *arg);
    
    int main(int argc,char *argv[])
    {
        pthread_t id1;
        pthread_t id2;
        pthread_t id3;
        
        sem_init(&sem1, 0, 100);
        sem_init(&sem2, 0, 0);
        pthread_mutex_init(&mutex,NULL);
        queue = create_duilie(queue);
        
        pthread_create(&id1,NULL,func1,NULL);
        pthread_create(&id2,NULL,func2,NULL);
        pthread_create(&id3,NULL,func3,NULL);
        
        pthread_join(id1,NULL);
        pthread_join(id2,NULL);
        pthread_join(id3,NULL);
        
        sem_destroy(&sem1);
        sem_destroy(&sem2);
        
        return 0;
    }
    
    void *func1(void *arg)
    {
        while(1)
        {
            sem_wait(&sem1);
            
            pthread_mutex_lock(&mutex);
            num++;
            add_duilie(queue,num);
            printf("%d号顾客到来\t还有%d个顾客\n",num,len_duilie(queue));
            pthread_mutex_unlock(&mutex);
            
            sem_post(&sem2);
            sleep(1);
        
        }
        pthread_exit(NULL);
    }
    
    void *func3(void *arg)
    {
        while(1)
        {
            sem_wait(&sem1);
            
            pthread_mutex_lock(&mutex);
            num++;
            add_duilie(queue,num);
            printf("%d号顾客到来\t还有%d个顾客\n",num,len_duilie(queue));
            pthread_mutex_unlock(&mutex);
            sem_post(&sem2);
            sleep(1);
        
        }
        pthread_exit(NULL);
    }
    
    void *func2(void *arg)
    {
        while(1)
        {
            sem_wait(&sem2);
            int num1;
            
            pthread_mutex_lock(&mutex);
            num1 = del_duilie(queue);
            pthread_mutex_unlock(&mutex);
            
            printf("%d号顾客离去\n",num1);
            sem_post(&sem1);
            sleep(3);
        }
        pthread_exit(NULL);
    }
    

    相关文章

      网友评论

      本文标题:系统编程

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