一、文件管理:stat、access、chmod、truncate、link函数
1.stat()
#include <sys/stat.h>
int stat(const char *path,struct stat *buf);
功能:用于获取文件的属性;
参数说明:*path:文件路径;
*buf:接受获取到的文件属性;文件属性存储在inode中,函数从inode结构体中获取文 件信息
返回值说明:成功:0
不成功:-1并设置errno
【案例1】使用stat函数获取文件属性,并输出文件的大小。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(){
struct stat tempSBuf;
int tempRet = 2;
tempRet = stat("a.out", &tempSBuf);
if(tempRet == -1){
perror("stat error:");
exit(1);
}//of if
printf("len = %d\n", tempSBuf.st_size);
return 0;
}//of main
运行结果如图:
2.access()
#include <unistd.h>
int access(const char *pathname, int mode);
功能:用于测试文件是否拥有某种权限;
参数说明:*pathname:文件名;
*mode:取值有4个:R_OK,W_OK,X_OK,F_OK;前面3个是测试文件是否有读、写、执行权限,最后一个测试文件是否存在。
返回值说明:成功:0,表示文件存在或具有某种权限。
不成功:-1并设置errno
3.chmod()
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
功能:用于修改文件的访问权限;
参数说明:*path:路径名;
*mode:传递修改后的权限。
返回值说明:成功:0,表示文件存在或具有某种权限;
不成功:-1并设置errno
4.truncate()
#include <sys/stat.h>
int truncate(const char *path, off_t length);
功能:用于修改文件大小,常用于扩展文件,其功能与lseek函数类似;
参数说明:*path:路径名;
*length:设置文件大小。
返回值说明:成功:0
不成功:-1并设置errno
二、进程控制:fork()、exec函数族、wait()、exit()
1.1创建进程
#include <unistd.h>
pid_t fork(void);
【案例1】使用fork函数创建一个进程,创建成功后父子进程分别执行不同的功能。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
pid_t tempPid;
tempPid = fork();
if(tempPid == -1){
perror("fork error");
}else if(tempPid > 0){//parent
printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
}else{//child
printf("child process, pid = %d, ppid = %d\n", getpid(), getppid());
}//of if
printf("......finish......\n");
return 0;
}//of main
运行结果如下:
出现的问题:多次执行该程序会发现child process后输出的ppid不等于parent process的pid,而可能等于1。出现这种情况是因为父进程先于子进程终止,子进程变成“孤儿进程”,后面由init进程来接收。
1.2创建多个进程
int i;
for(i = 0; i < 2; i++){
tempPid = fork();
}
【案例】
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
pid_t tempPid;
int i;
for(i = 0; i < 2; i ++){
if((tempPid = fork()) == 0){
break;
}//of if
}//of for i
if(tempPid == -1){
perror("fork error");
}else if(tempPid > 0){//parent
printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
}else{//child
printf("I am child process = %d, pid = %d, ppid = %d\n", i + 1, getpid(), getppid());
}//of if
printf("......finish......\n");
return 0;
}//of main
运行结果如下:
问题及原因
(1)终止的先后顺序随机:子进程的编号不是递增的是因为在Linux系统中,子进程应由父进程回收,但是当子进程被创建后,它与它的父进程及其它进程共同竞争系统资源,所以父子进程执行的顺序是不确定的,终止的先后顺序也是不确定的。
(2)运行完程序后依然闪烁:终端提示符后面仍然有子进程信息打印而命令提示符在最后一行的开头闪烁是因为Shell命令提示符也是一个进程,它需要和新建进程一起竞争CPU。
1.3进程的执行顺序:利用sleep函数,暂缓进程执行
【案例】
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
pid_t tempPid;
int i;
for(i = 0; i < 2; i ++){
if((tempPid = fork()) == 0){
break;
}//of if
}//of for i
if(tempPid == -1){
perror("fork error");
}else if(tempPid > 0){//parent
sleep(2);
printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
}else{//child
sleep(i);
printf("I am child process = %d, pid = %d, ppid = %d\n", i + 1, getpid(), getppid());
}//of if
printf("......finish......\n");
return 0;
}//of main
运行结果如下:
心得总结:通过这次的实验让我更深刻地明白了老师上课讲授的进程概念,理解了进程在计算机内部运行的方式和进程之间的关系以及怎样初步操作进程。