系统编程

文件操作

打开文件

使用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);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容