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进程收养