文件操作
打开文件
使用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);
}