文章目录
- 1)输出Linux下的c也不是太难嘛!在linux下编辑,编译,运行
- 2)编写一个简单地c语言程序,根据输入的两个整数求平均值并且在终端输出,通过gcc编译器得到它的汇编程序文件。
- 3)编写一个c语言程序,打印输出所有的“水仙花数”
- 4)创建文件init_test.c,并用valgrind检测内存错误,并把代码修改正确
- 5)创建文件test2.c,并用valgrind检测内存错误,并把代码修改正确;
- 6)创建文件test3.c,并用valgrind检测内存错误,并把代码修改正确;
- 7)创建文件test4.c,并用valgrind检测内存错误,并把代码修改正确;
- 8)创建文件test5.c,并用valgrind检测内存错误,并把代码修改正确;
- 9)创建文件file1,写入字符串“abcdefghijklmn”; 创建文件file2,写入字符串“ABCDEFGHIJKLMN”;读取file1中的内容,写入file2,使file2中的字符串内容为“ ABCDEFGHIJKLMNabcdefghijklmn”
- 10)创建新文件,该文件具有用户读写权限。采用dup/dup2/fcntl复制一个新的文件描述符,通过新文件描述符向文件写入“class_name”字符串;通过原有的文件描述符读取文件中的内容,并且打印显示;
- 11)输入文件名称,能够判断文件类型,判断实际用户对该文件具有哪些存取权限;要求打印出文件类型信息,inode节点编号,链接数目,用户id,组id,文件大小信息;修改文件的权限为当前用户读写,组内用户读写,组外用户无权限。
- 12)新建文件,设置文件权限屏蔽字为0;建立该文件的硬链接文件,打印硬链接文件的inode节点号和文件大小;建立该文件的软链接文件,打印软链接文件的inode节点号和文件大小;打印软链接文件中的内容;打印源文件的inode节点号,文件大小和链接数目;调用unlink对源文件进行操作,打印源文件链接数目;
- 13)新建/home/user目录;把当前工作路径移至/home/user目录;打印当前工作路径;
- 14)编写程序完成以下功能:递归遍历/home目录,打印出所有文件和子目录名称及节点号。判断文件类型,如果是子目录,继续进行递归遍历,直到遍历完所有子目录为止。
- 15)打印当前所有环境变量的值;添加新的环境变量NEWENV=first;修改环境变量NEWENV的值为second;打印环境变量NEWENV的值。
- 16)打印字符串“hello world!”,在打印字符串“hello world!”前调用三次fork,分析打印结果。
- 17)在子进程中打开文件file1,写入自己的“班级_姓名_学号”,父进程读取file1中的内容,并且打印显示。在父进程中获取已经结束的子进程的状态信息,打印该信息,并且打印结束的子进程的进程号。
- 18)在父进程中定义变量n,在子进程中对变量n进行++操作;并且打印变量n的值,打印子进程pid;在父进程中打印变量n的值,并且打印父进程pid。要求分别用fork和vfork创建子进程。
- 19)创建子进程一,在子进程中递归打印/home目录中的内容(用exec系列函数调用第二次实验中的代码完成此功能);子进程结束的时候完成以下功能:打印字符串“Child process exited!”。打印子进程标识符,打印父进程标识符。创建子进程二, 打印子进程运行环境中环境变量“USER”的值,通过exec系列中的某个函数设置子进程”USER”环境变量值为“zhangsan”,并且让该子进程完成以下命令:“ls –li /home”.
- 20)编程实现以下功能:主线程实现以下功能: ① 定义全局变量key;② 创建两个线程;③ 如果线程正常结束,得到线程的结束状态值,并打印;线程一完成以下操作:① 设置全局变量key的值为字符串“hello world”;② 打印3次字符串“当前线程ID:key值”;③ 接收到线程二发送的取消请求信号后退出;④ 结束的时候打印字符串“thread1 ,exited!:key值”;线程二完成以下操作:① 设置key值为6;② 给线程一发送取消请求信号;
- 21)用多线程实现生产者消费者,至少有两个消费者和两个生产者
- 22)利用匿名管道实现父子进程间通信,要求父进程发送字符串“hello child”给子进程;子进程收到父进程发送的数据后,给父进程回复“hello farther”;父子进程通信完毕,父进程依次打印子进程的退出状态以及子进程的pid
- 23)利用匿名管道实现兄弟进程间通信,要求兄进程发送字符串“This is elder brother ,pid is (兄进程进程号)”给第进程;第进程收到兄进程发送的数据后,给兄进程回复“This is younger brother ,pid is(第进程进程号)”;
- 24)利用有名管道文件实现进程间通信,要求写进程向有名管道文件写入10次“hello world”;读进程读取有名管道文件中的内容,并依次打印。
- 25)进程A向进程B发送SIGUSR1信号;进程B收到信号后,打印字符串“receive SIGUSR1”;要求用kill函数和signal函数实现以上功能;
- 26)调用setitimer函数分别触发SIGALRM信号,SIGVTALRM信号,SIGPROF信号 ;(可以由多进程分别触发每个信号)编写信号安装函数,在该函数内部能判断接受到的是什么信号,并把信号打印出来。
- 27)进程A向进程B发送SIGUSR1信号;进程B收到信号后,打印字符串“receive SIGUSR1”;要求用sigqueue函数和sigaction函数实现以上功能;
- 28)进程A向进程B发送信号,该信号的附带信息为一个值为20的整数;进程B完成接收信号的功能,并且打印出信号名称以及随着信号一起发送过来的整形变量值。
- 29)创建共享内存,写进程通过键盘不断向内存写入“hello world”;如果结束写操作,则通过键盘输入“end”;读进程从共享内存读取数据,并打印。直到读到“end”为止。
- 30)进程A向消息队列发送消息“hello,world”,进程B从消息队列读取消息,并打印。进程C向消息队列发送“自己在姓名”,进程D从消息队列中取出姓名字符串,并打印
1)输出Linux下的c也不是太难嘛!在linux下编辑,编译,运行
(1)创建test.c文件,然后编辑 test.c文件
(2)编写程序,保存退出
#include<stdio.h>
int main(){
printf("Linux下的C语言不是太难嘛!");
printf("Linux下的C语言不是太难嘛!");
return 0;
}
(3)输入 gcc test.c -o test编译文件,并生成test可执行程序文件
(4)输入 ./test 运行 test
2)编写一个简单地c语言程序,根据输入的两个整数求平均值并且在终端输出,通过gcc编译器得到它的汇编程序文件。
#include <stdbool.h>
#include<stdio.h>
int main() {
double a,b;
double c;
printf("请输入两个数值:");
scanf("%lf%lf",&a,&b);
c=(a+b)/2;
printf("%.2lf",c);
return 0;
}
3)编写一个c语言程序,打印输出所有的“水仙花数”
#include<stdio.h>
int main(){
int a,b,c,d;
a = b = c = 0;
printf("请输入你要输入的范围:\n");
scanf("%d",&d);
for(int i = 100; i <d; i++) {
a = i % 10;
b = (i / 10) % 10;
c = i / 100;
if((a*a*a + b*b*b + c*c*c) == i) {
printf("%d\n" , i);
}
}
}
4)创建文件init_test.c,并用valgrind检测内存错误,并把代码修改正确
(1)创建文件init_test.c
(2)用valgrind检测内存错误
(3)修改代码
#include<stdio.h>
int main(void){
int x;
scanf("%d",&x);
if(x==0)
printf("x is zero");
else
printf("x is not zero");
return 0;
}
(4)Valgrind验证
5)创建文件test2.c,并用valgrind检测内存错误,并把代码修改正确;
(1)创建文件test2.c
(2)用valgrind检测内存错误
(3)修改代码
#include<stdio.h>
#include<stdlib.h>
void fun(){
int *p=(int *)malloc(10*sizeof(int));
p[9]=0;
free(p);
}
int main(int argc,char* argv[])
{
fun();
return 0;
}
(4)valgrind验证代码
6)创建文件test3.c,并用valgrind检测内存错误,并把代码修改正确;
(1)创建test3.c文件
(2)用valgrind检测内存错误
(3)修改代码
#include<stdlib.h>
#include<stdio.h>
int main(int argc,char *argv[])
{
int i=0;
int len=4;
int* pt=(int *)malloc(len*sizeof(int));
int* p=pt;
for( i=0;i<len-1;i++){
*p++;
}
*p=5;
printf("the value of p equal:%d",*p);
free(pt);
return 0;
}
(4) valgrind测试
7)创建文件test4.c,并用valgrind检测内存错误,并把代码修改正确;
(1)创建test4.c文件
(2)用valgrind检测错误
(3)修改代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argv[])
{
char x[50];
int i;
for(i=0;i<50;i++)
{
x[i]=i+1;
}
strncpy(x+20,x,20);//OK
strncpy(x+21,x,21);
strncpy(x,x+20,20); //ok
strncpy(x,x+20,20);
x[39]='\0';
strcpy(x,x+20);
x[39]=39;
x[40]='\0';
strcpy(x,x+21);
return 0;
}
(4) valgrind测试
8)创建文件test5.c,并用valgrind检测内存错误,并把代码修改正确;
(1)创建test5.c文件
(2)用valgrind进行测试
(3)修改代码
#include<stdlib.h>
#include<stdio.h>
int main(int argc,char *argv[]){
int i;
char* p=(char*)malloc(10);
char* pt=p;
for(i=1;i<10;i++)
{
p[i]='z';
}
pt[1]='x';
free(pt);
return 0;
}
(4)用 valgrind验证代码正确
9)创建文件file1,写入字符串“abcdefghijklmn”; 创建文件file2,写入字符串“ABCDEFGHIJKLMN”;读取file1中的内容,写入file2,使file2中的字符串内容为“ ABCDEFGHIJKLMNabcdefghijklmn”
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
int main() {
int fd1,fd2;
fd1=open("file1",O_CREAT|O_RDWR,S_IRWXU);
if(fd1< 0) {
perror("open :");
printf("errno is:%d \n",errno);
} else
printf("open ok\n");
fd2=open("file2",O_CREAT|O_RDWR,S_IRWXU);
if(fd2< 0) {
perror("open:");
printf("errno is:%d \n,errno");
} else
printf("open OK \n");
int fdw1,fdw2;
fdw1=write(fd1,"abcdefghijklmn",15);
printf("fdw1:%d\n",fdw1);
if(fdw1!=15) {
perror("write fd1:");
} else
printf("write OK\n");
lseek(fd2,16,SEEK_SET);
char buf[20]="ABCDEFGHIJKLMN";
fdw2=write(fd2,buf,20);
if(fdw2<0)
perror ("write fd2:");
else
printf("write OK\n");
lseek (fd1,0,SEEK_SET);
lseek(fd2,0,SEEK_SET);
char re[28];
read(fd1,re,14);
write(fd2,re,14);
close(fd1);
close(fd2);
return 0;
}
10)创建新文件,该文件具有用户读写权限。采用dup/dup2/fcntl复制一个新的文件描述符,通过新文件描述符向文件写入“class_name”字符串;通过原有的文件描述符读取文件中的内容,并且打印显示;
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
int main() {
int fd1,fd2;
fd1=open("file",O_RDWR|O_CREAT,0644);
fd2=dup(fd1);
char str[30];
char name[30]="class_name";
lseek(fd2,0,SEEK_SET);
write(fd2,name,30);
lseek(fd1,0,SEEK_SET);
read(fd1,str,30);
printf("%s",str);
close(fd1);
return 0;
}
11)输入文件名称,能够判断文件类型,判断实际用户对该文件具有哪些存取权限;要求打印出文件类型信息,inode节点编号,链接数目,用户id,组id,文件大小信息;修改文件的权限为当前用户读写,组内用户读写,组外用户无权限。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc,char *argv[]) {
if(argc < 2) {
printf("Please input the filename!\n");
return 0;
}
struct stat statbuf;
int i;
for(i = 1; i < argc; i++) {
if(lstat(argv[i],&statbuf) < 0)
perror("lstat");
char *buf;
if(S_ISREG(statbuf.st_mode))
buf = "Regular file!";
else if(S_ISDIR(statbuf.st_mode))
buf = "Directory file!";
else if(S_ISCHR(statbuf.st_mode))
buf = "Char file!";
else
buf = "Other file!";
printf("The %s is:%s\n",argv[i],buf);
printf("The %s mode is:%d\n",argv[i],statbuf.st_mode);
printf("The %s inode is:%d\n",argv[i],statbuf.st_ino);
printf("The %s uid is:%d\n",argv[i],statbuf.st_uid);
printf("The %s gid is:%d\n",argv[i],statbuf.st_gid);
printf("The %s size is:%d\n",argv[i],statbuf.st_size);
printf("The %s link num is:%d\n",argv[i],statbuf.st_nlink);
}
for(i = 1; i < argc; i++) {
if(access(argv[i],R_OK))
printf("The user can read the %s\n",argv[1]);
else if(access(argv[i],W_OK))
printf("The user can write the %s\n",argv[1]);
else if(access(argv[i],X_OK))
printf("The user can read and write the %s\n",argv[1]);
}
for(i = 1; i < argc; i++) {
if(chmod(argv[i],0660) < 0)
perror("chmod");
else
printf("The file.mode chmod successful!\n");
}
return 0;
}
12)新建文件,设置文件权限屏蔽字为0;建立该文件的硬链接文件,打印硬链接文件的inode节点号和文件大小;建立该文件的软链接文件,打印软链接文件的inode节点号和文件大小;打印软链接文件中的内容;打印源文件的inode节点号,文件大小和链接数目;调用unlink对源文件进行操作,打印源文件链接数目;
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
umask(0);
struct stat statbuf;
int fd = open("file",O_CREAT|O_RDWR);
if(fd < 0)
perror("open");
char *str = "hello world";
if(write(fd,str,strlen(str)) < 0)
perror("write");
link("./file","./hard_link");
if(lstat("hard_link",&statbuf) < 0)
perror("lstat");
printf("The hard_link's inode is: %d\n",statbuf.st_ino);
printf("The hard_link's size is: %d\n",statbuf.st_size);
symlink("file","sort_link");
if(lstat("sort_link",&statbuf) < 0)
perror("lstat");
printf("The sort_link's inode is: %d\n",statbuf.st_ino);
printf("The sort_link's size is: %d\n",statbuf.st_size);
char buf[4];
readlink("sort_link",buf,4);
printf("The sort_link is: %s\n",buf);
if(lstat("file",&statbuf) < 0)
perror("lstat");
printf("The file's inode is: %d\n",statbuf.st_ino);
printf("The file's size is: %d\n",statbuf.st_size);
printf("The frist linknum is: %d\n",statbuf.st_nlink);
unlink("file");
if(lstat("file",&statbuf) < 0)
perror("lstat");
printf("The second linknum is: %d\n",statbuf.st_nlink);
close(fd);
return 0;
}
13)新建/home/user目录;把当前工作路径移至/home/user目录;打印当前工作路径;
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
char str[128];
if(getcwd(str,128) < 0)
perror("getwcd");
else
printf("The workdir is:%s\n",str);
if(mkdir("/home/user",0666) < 0)
perror("mkdir");
else
printf("The dir create successfully!\n");
if(chdir("/home/user") < 0)
perror("chdir");
else {
getcwd(str,128);
printf("The workdir is:%s\n",str);
}
rmdir("/home/user");
return 0;
}
14)编写程序完成以下功能:递归遍历/home目录,打印出所有文件和子目录名称及节点号。判断文件类型,如果是子目录,继续进行递归遍历,直到遍历完所有子目录为止。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
void show(char *path) {
DIR *dir;
char str[128];
struct dirent *dirp;
struct stat statbuf;
dir = opendir(path);
if(dir) {
while((dirp = readdir(dir)) != NULL) {
sprintf(str,"%s/%s",path,dirp->d_name);
if(lstat(str,&statbuf) < 0)
perror("lstat");
if(dirp->d_name[0] == '.')
continue;
if(S_ISDIR(statbuf.st_mode)) {
show(str);
printf("The dirent's name is: %s\n",dirp->d_name);
printf("The dirent's inode is: %d\n",dirp->d_ino);
} else {
printf("The file's name is: %s\n",dirp->d_name);
printf("The file's inode is: %d\n",dirp->d_ino);
}
}
} else
perror("opendir");
closedir(dir);
}
int main() {
show("/home");
return 0;
}
15)打印当前所有环境变量的值;添加新的环境变量NEWENV=first;修改环境变量NEWENV的值为second;打印环境变量NEWENV的值。
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
extern char **environ;
int main() {
char **env = environ;
while(*env) {
printf("The env is: %s\n",*env);
env++;
}
putenv("NEWENV=first");
char *str;
str = getenv("NEWENV");
printf("The NEWENV is: %s\n",str);
if(setenv("NEWENV","second",1) < 0)
perror("setenv");
str = getenv("NEWENV");
printf("The NEWENV is: %s\n",str);
return 0;
}
16)打印字符串“hello world!”,在打印字符串“hello world!”前调用三次fork,分析打印结果。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
fork();
fork();
fork();
printf("hello world!!!\n");
return 0;
}
17)在子进程中打开文件file1,写入自己的“班级_姓名_学号”,父进程读取file1中的内容,并且打印显示。在父进程中获取已经结束的子进程的状态信息,打印该信息,并且打印结束的子进程的进程号。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
int main() {
int fd,pid;
fd = open("file",O_CREAT|O_RDWR,S_IRWXU);
if(fd< 0)
perror("open");
pid = fork();
if(pid == 0) {
printf("This is the child!\n");
char str[128] = "class__name_× × × × ×";
if(write(fd,str,128) < 0)
perror("write");
exit(5);
} else {
printf("This is the father!\n");
char buf[128];
int n,status;
if(read(fd,buf,128) < 0)
perror("read");
printf("The buf is: %s\n",buf);
if(wait(&status) < 0)
perror("perror");
if(WIFEXITED(status))
n = WEXITSTATUS(status);
else
printf("wait error!\n");
printf("The child's pid is: %d\n",pid);
printf("The child exit status is: %d\n",n);
}
return 0;
}
18)在父进程中定义变量n,在子进程中对变量n进行++操作;并且打印变量n的值,打印子进程pid;在父进程中打印变量n的值,并且打印父进程pid。要求分别用fork和vfork创建子进程。
创建fork.c文件,编写代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
int n = 1;
if(fork() == 0) {
printf("This is child,the pid is%d\n",getpid());
printf("The n is: %d\n",++n);
} else {
printf("This is father,the pid is%d\n",getpid());
printf("The n is: %d\n",n);
}
return 0;
}
创建vfork.c文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int n = 1;
pid_t pid;
pid = vfork();
if(pid < 0)
perror("vfork");
else if(pid == 0) {
printf("This is child,the child's pid is: %d\n",getpid());
printf("The n is: %d\n",++n);
exit(0);
} else {
printf("This is father,the father's pid is: %d\n",getpid());
printf("The n is: %d\n",n);
}
return 0;
}
19)创建子进程一,在子进程中递归打印/home目录中的内容(用exec系列函数调用第二次实验中的代码完成此功能);子进程结束的时候完成以下功能:打印字符串“Child process exited!”。打印子进程标识符,打印父进程标识符。创建子进程二, 打印子进程运行环境中环境变量“USER”的值,通过exec系列中的某个函数设置子进程”USER”环境变量值为“zhangsan”,并且让该子进程完成以下命令:“ls –li /home”.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void fun() {
printf("\n");
printf("Child process exited!!!\n");
printf("The child's pid is: %d\n",getpid());
printf("The father's pid is %d\n",getppid());
printf("\n");
}
int main() {
pid_t pid;
pid = vfork();
if(pid <0)
perror("vfork");
else if(pid == 0) {
printf("This is the child1 !!!\n");
atexit(fun);
if((execl("/home/wang/test/file/test6/test","test",NULL)) < 0) {
perror("execl");
exit(0);
}
} else {
printf("This is the father !!!\n");
if(vfork() == 0) {
printf("This is the child2 !!!\n");
printf("The child2's father's pid is: %d\n",getppid());
char * env[] = {"USER=zhangsan",NULL};
char *p;
p = getenv("USER");
if(p) {
printf("The user is: %s\n",p);
}
system("ls -li /home");
if((execle("/bin/env","env",NULL,env)) < 0)
perror("execle");
exit(1);
}
}
return 0;
}
20)编程实现以下功能:主线程实现以下功能: ① 定义全局变量key;② 创建两个线程;③ 如果线程正常结束,得到线程的结束状态值,并打印;线程一完成以下操作:① 设置全局变量key的值为字符串“hello world”;② 打印3次字符串“当前线程ID:key值”;③ 接收到线程二发送的取消请求信号后退出;④ 结束的时候打印字符串“thread1 ,exited!:key值”;线程二完成以下操作:① 设置key值为6;② 给线程一发送取消请求信号;
创建 Thread_test.c文件,编写程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <pthread.h>
pthread_key_t key;
void cleanup(void *arg) {
printf("%s\n",(char *)arg);
}
void *child_thread1(void *arg) {
char *str = "Hello World";
printf("The child_thread1 run!\n");
printf("The thread id is: %d\n",syscall(SYS_gettid));
if(pthread_setspecific(key,str) < 0)
perror("pthread_setspecific");
char *get_key = (char *)pthread_getspecific(key);
printf("The thread1's key is: %s\n",get_key);
pthread_cleanup_push(cleanup,"Thread1,exited!");
pthread_cleanup_pop(1);
}
void *child_thread2(void *arg) {
int num = 6;
printf("The child_thread2 run!\n");
if(pthread_cancel((pthread_t)arg) < 0)
perror("pthread_cancle");
if(pthread_setspecific(key,(void *)num) < 0)
perror("pthread_setspecific");
int *get_key = (int *)pthread_getspecific(key);
printf("The thread2's key is: %d\n",get_key);
pthread_cleanup_push(cleanup,"Thread2,exited!");
pthread_cleanup_pop(1);
}
void *thread(void *arg) {
pthread_t tid1,tid2;
void *tret1,*tret2;
printf("This is the main pthread!\n");
if(pthread_key_create(&key,NULL) < 0)
perror("phtread_key_create");
if(pthread_create(&tid1,NULL,(void *)child_thread1,NULL) < 0)
perror("pthread_create");
pthread_join(tid1,&tret1);
printf("The pthread1 exited is: %d\n",(long)tret1);
if(pthread_create(&tid2,NULL,(void *)child_thread2,&tid1) < 0)
perror("pthread_create");
pthread_join(tid2,&tret2);
printf("The pthread2 exited is: %d\n",(long)tret2);
}
int main() {
pthread_t id;
if(pthread_create(&id,NULL,(void *)thread,NULL) < 0)
perror("pthread_create");
sleep(1);
return 0;
}
21)用多线程实现生产者消费者,至少有两个消费者和两个生产者
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#define BUFFER_SIZE 10
#define SEM_KEY 1234
struct circle_buf {
int r;
int w;
int buf[BUFFER_SIZE];
};
int semid;
struct sembuf semaphore;
struct circle_buf cbuf;
void writecbuf(struct circle_buf *cbuf, int val) {
cbuf->buf[cbuf->w] = val;
cbuf->w = (cbuf->w + 1) % BUFFER_SIZE;
}
int readcbuf(struct circle_buf *pcbuf) {
int value = pcbuf->buf[pcbuf->r];
pcbuf->buf[pcbuf->r] = -1;
pcbuf->r = (pcbuf->r + 1) % BUFFER_SIZE;
return value;
}
void outcbuf(struct circle_buf *pcbuf) {
int i = 0;
printf("缓冲区各单元的值:");
for (i = 0; i < BUFFER_SIZE; ++i) {
printf("%d%c", pcbuf->buf[i],
(i == BUFFER_SIZE - 1) ? '\n' : ' ');
}
}
int initsembuf(void) {
int sem = 0;
if ((semid = semget(SEM_KEY, 3, IPC_CREAT | 0666)) >= 0) {
sem = 1;
semctl(semid, 0, SETVAL, sem);
sem = BUFFER_SIZE;
semctl(semid, 1, SETVAL, sem);
sem = 0;
semctl(semid, 2, SETVAL, sem);
return 1;
} else {
return 0;
}
}
void pmutex(void) {
semaphore.sem_num = 0;
semaphore.sem_op = -1;
semaphore.sem_flg = SEM_UNDO;
semop(semid, &semaphore, 1);
}
void vmutex(void) {
semaphore.sem_num = 0;
semaphore.sem_op = 1;
semaphore.sem_flg = SEM_UNDO;
semop(semid, &semaphore, 1);
}
void pempty(void) {
semaphore.sem_num = 1;
semaphore.sem_op = -1;
semaphore.sem_flg = SEM_UNDO;
semop(semid, &semaphore, 1);
}
void vempty(void) {
semaphore.sem_num = 1;
semaphore.sem_op = 1;
semaphore.sem_flg = SEM_UNDO;
semop(semid, &semaphore, 1);
}
void pfull(void) {
semaphore.sem_num = 2;
semaphore.sem_op = -1;
semaphore.sem_flg = SEM_UNDO;
semop(semid, &semaphore, 1);
}
void vfull(void) {
semaphore.sem_num = 2;
semaphore.sem_op = 1;
semaphore.sem_flg = SEM_UNDO;
semop(semid, &semaphore, 1);
}
void sigend(int sig) {
semctl(semid, 3, IPC_RMID);
exit(0);
}
void *productthread(void *arg) {
int val = *(int *)arg;
while (1) {
pempty();
pmutex();
writecbuf(&cbuf, val);
printf("生产者%d写入缓冲区的值=%d.\n", val, val);
outcbuf(&cbuf);
vmutex();
vfull();
}
return NULL;
}
void *consumerthread(void *arg) {
int cid = *(int *)arg;
int val = 0;
while (1) {
pfull();
pmutex();
val = readcbuf(&cbuf);
printf("消费者%d取走的产品的值=%d.\n", cid, val);
outcbuf(&cbuf);
vmutex();
vempty();
}
return NULL;
}
int main(int argc, char *argv[]) {
while (!initsembuf()) {
;
}
signal(SIGINT, sigend);
signal(SIGTERM, sigend);
int i = 0;
int ret = 0;
int consnum = 0;
int prodnum = 0;
cbuf.r = 0;
cbuf.w = 0;
memset(cbuf.buf, 0, BUFFER_SIZE);
printf("请输入生产者进程的数目:");
scanf("%d", &prodnum);
int *prosarg = (int *)malloc(prodnum * sizeof(int));
pthread_t *prosid = (pthread_t *)malloc(prodnum * sizeof(pthread_t));
printf("请输入消费者进程的数目:");
scanf("%d", &consnum);
int *consarg = (int *)malloc(consnum * sizeof(int));
pthread_t *consid = (pthread_t *)malloc(consnum * sizeof(pthread_t));
for (i = 0; i < prodnum; ++i) {
prosarg[i] = i + 1;
ret = pthread_create(&prosid[i], NULL, productthread,
(void *)&prosarg[i]);
printf("消费者prosid[%d] = %lu\n", i + 1, prosid[i]);
if (ret != 0) {
printf("创建生产者线程失败!");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < consnum; ++i) {
consarg[i] = i + 1;
ret = pthread_create(&consid[i], NULL, consumerthread,
(void *)&consarg[i]);
printf("生产者consid[%d] = %lu\n", i + 1, consid[i]);
if (ret != 0) {
printf("创建消费者线程失败!");
exit(EXIT_FAILURE);
}
}
sleep(10);
return 0;
}
22)利用匿名管道实现父子进程间通信,要求父进程发送字符串“hello child”给子进程;子进程收到父进程发送的数据后,给父进程回复“hello farther”;父子进程通信完毕,父进程依次打印子进程的退出状态以及子进程的pid
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int fd1[2],fd2[2];
pipe(fd1);
pipe(fd2);
int pid;
pid = fork();
if(pid < 0)
perror("fork");
else if(pid == 0) {
close(fd1[0]);
close(fd2[1]);
char str[12];
printf("This is the child!\n");
if(read(fd2[0],str,12) > 0) {
printf("Received the news: %s\n",str);
if(write(fd1[1],"hello father",12) < 0)
perror("write");
} else
perror("read");
exit(5);
} else {
int status;
printf("This is the father!\n");
close(fd1[1]);
close(fd2[0]);
char buf[24] = "hello child";
if(write(fd2[1],buf,12) < 0)
perror("write");
else {
printf("Send news successful!\n");
}
wait(&status);
if(WIFEXITED(status)) {
printf("The child's pid is: %d\n",pid);
printf("The child's exited status is: %d\n",WEXITSTATUS(status));
}
}
return 0;
}
23)利用匿名管道实现兄弟进程间通信,要求兄进程发送字符串“This is elder brother ,pid is (兄进程进程号)”给第进程;第进程收到兄进程发送的数据后,给兄进程回复“This is younger brother ,pid is(第进程进程号)”;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main() {
int fd1[2],fd2[2];
pipe(fd1);
pipe(fd2);
int pid;
pid = fork();
if(pid == 0) {
printf("This is the elder brother!\n");
printf("The elder's father's pid is: %d\n",getppid());
close(fd1[1]);
close(fd2[0]);
char str1[64],str2[64];
sprintf(str1,"This is the elder brother,pid is %d",getpid());
if(write(fd2[1],str1,64) < 0)
perror("write");
if(read(fd1[0],str2,64) < 0)
perror("read");
else
printf("The news from younger is: %s\n",str2);
} else {
if(fork() == 0) {
printf("This is the younger brother!\n");
printf("The younger's father's pid is: %d\n",getppid());
close(fd1[0]);
close(fd2[1]);
char buf1[64],buf2[64];
if(read(fd2[0],buf1,64) > 0) {
printf("The news form elder is: %s\n",buf1);
sprintf(buf2,"This is the younger brother,pid is %d",getpid());
if(write(fd1[1],buf2,64) < 0)
perror("write");
} else
perror("read");
}
}
return 0;
}
24)利用有名管道文件实现进程间通信,要求写进程向有名管道文件写入10次“hello world”;读进程读取有名管道文件中的内容,并依次打印。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main() {
int pid,fd;
if(mkfifo("fifotest",0666) < 0)
perror("mkfifo");
pid = fork();
if(pid < 0)
perror("fork");
else if(pid == 0) {
printf("This is the write process!\n");
int fd = open("fifotest",0666);
for(int i = 0; i < 10; i++) {
if(write(fd,"hello world",12) < 0)
perror("write");
sleep(1);
}
close(fd);
} else {
char str[128];
printf("This is the read process!\n");
int fd1 = open("fifotest",0666);
for(int i = 0; i < 10; i++) {
if(read(fd1,str,128) < 0)
perror("read");
else
printf("%s\n",str);
}
system("rm -f fifotest");
}
return 0;
}
25)进程A向进程B发送SIGUSR1信号;进程B收到信号后,打印字符串“receive SIGUSR1”;要求用kill函数和signal函数实现以上功能;
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
void fun(int sig)
{
if(sig=SIGUSR1){
printf("Received SIGUSR1!\n");
}
}
int main(){
printf("This is A process,mypid is:%d\n",getpid());
signal(SIGUSR1,fun);
pause();
return 0;
}
第三步:处理结果
因为程序中有pause()语句,那么程序运行到此就会停下知道有信号发送给此进程。
然后新建一个终端,在终端输入kill -SIGUSR 3701,那么第二个进程就会发送SIGUSR1信号给pid为3701的进程,也就是进程A。之后程序输出字符串,进程结束。
编写killend.c文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
void fun(int sig) {
if(sig == SIGUSR1)
printf("Reseived SIGUSR1!\n");
}
int main() {
int pid;
if(signal(SIGUSR1,fun) < 0)
perror("signal");
pid = fork();
if(pid < 0)
perror("fork");
else if(pid == 0) {
printf("This is B process!\n");
sleep(2);
} else {
printf("This is A process!\n");
if(kill(pid,SIGUSR1) < 0)
perror("kill");
return 0;
}
}
26)调用setitimer函数分别触发SIGALRM信号,SIGVTALRM信号,SIGPROF信号 ;(可以由多进程分别触发每个信号)编写信号安装函数,在该函数内部能判断接受到的是什么信号,并把信号打印出来。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
void fun(int sig) {
if(sig == SIGALRM)
printf("Received the SIGALRM!\n");
else if(sig == SIGVTALRM)
printf("Receive the SIGVTALRM!\n");
else if(sig == SIGPROF)
printf("Receive the SIGPROf!\n");
}
int main() {
if(signal(SIGALRM,fun) < 0)
perror("signal");
if(signal(SIGVTALRM,fun) < 0)
perror("signal");
if(signal(SIGPROF,fun) < 0)
perror("signal");
struct itimerval new_value1,new_value2,new_value3;
new_value1.it_value.tv_sec = 1;
new_value1.it_value.tv_usec = 0;
new_value1.it_interval.tv_sec = 2;
new_value1.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL,&new_value1,NULL);
new_value2.it_value.tv_sec = 1;
new_value2.it_value.tv_usec = 0;
new_value2.it_interval.tv_sec = 2;
new_value2.it_interval.tv_usec = 0;
setitimer(ITIMER_VIRTUAL,&new_value2,NULL);
new_value3.it_value.tv_sec = 1;
new_value3.it_value.tv_usec = 0;
new_value3.it_interval.tv_sec = 2;
new_value3.it_interval.tv_usec = 0;
setitimer(ITIMER_PROF,&new_value3,NULL);
while(1);
return 0;
}
27)进程A向进程B发送SIGUSR1信号;进程B收到信号后,打印字符串“receive SIGUSR1”;要求用sigqueue函数和sigaction函数实现以上功能;
创建send_signal.c 文件
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
int main() {
int pid;
printf ("请输入你将要发送给信号的进程的进程号:");
scanf ("%d",&pid); //输入接收信号的进程号
union sigval mysigval;
mysigval.sival_int = 20;
if (sigqueue(pid,SIGUSR1,mysigval) == -1) //向该进程发送信号,并且携带一个整数,这个整数会放在第二个参数中,一起发送给接受信号的进程
perror("sigqueue error");
else
printf ("send ok \n");
return 0;
}
创建receive_signal.c文件
#include<stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
int main() {
int pid;
printf ("pid is : %d \n",getpid());
void myFun(int sig);
struct sigaction act,oldact;
act.sa_handler = myFun; //定义接受信号的处理函数
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(SIGUSR1,&act,&oldact) == -1) //信号接收
perror("sigaction: \n");
pause();
return 0;
}
void myFun(int sig) {
printf("I got a signal:%d\n",sig);
printf ("receive SIGUSR1 \n");
}
28)进程A向进程B发送信号,该信号的附带信息为一个值为20的整数;进程B完成接收信号的功能,并且打印出信号名称以及随着信号一起发送过来的整形变量值。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int sig,siginfo_t* info,void *p) {
printf("The num is: %d\n",info->si_value.sival_int);
}
int main() {
int pid;
struct sigaction act;
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO;
pid = fork();
if(pid < 0)
perror("fork");
else if(pid == 0) {
printf("This is the receive process!\n");
if(sigaction(SIGUSR1,&act,NULL) < 0)
perror("sigaction");
while(1);
} else {
printf("This is the send process!\n");
union sigval mysigval;
mysigval.sival_int = 20;
sleep(1);
if(sigqueue(pid,SIGUSR1,mysigval) < 0)
perror("sigqueue");
}
return 0;
}
29)创建共享内存,写进程通过键盘不断向内存写入“hello world”;如果结束写操作,则通过键盘输入“end”;读进程从共享内存读取数据,并打印。直到读到“end”为止。
创建shmread.c文件
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>
#define MAXSIZE 1024
struct shm{
int write; //记录读进程是否已经将内容读取
char buffer[MAXSIZE];
};
int main()
{
int shmid;
struct shm *share;
void *shmptr = NULL;
if(shmid = shmget(0X44,MAXSIZE,0666|IPC_CREAT) < 0)
perror("shmget");
if((shmptr = shmat(shmid,0,0)) == (void *)-1)
perror("shmat");
printf("This is the read process!!!\n");
share = (struct shm *)shmptr;
while(1)
{
if(share->write != 0)
{
if(!strncmp(share->buffer,"end",3) == 0)
{
printf("%s",share->buffer);
share->write = 0;
}
else
break;
}
}
if(shmdt(shmptr) < 0)
perror("shmdt");
exit(0);
}
创建shmwrite.c文件
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>
#define MAXSIZE 1024
struct shm {
int write; //记录读进程是否已经将内容读取
char buffer[MAXSIZE];
};
int main() {
int shmid;
void *shmptr = NULL;
char str[MAXSIZE]; //存储输入的内容
struct shm *share;
if(shmid = shmget(0X44,MAXSIZE,0666|IPC_CREAT) < 0)
perror("shmget");
if((shmptr = shmat(shmid,0,0)) == (void *)-1)
perror("shmat");
printf("This is the write process!!!\n");
share = (struct shm *)shmptr;
while(1) {
if(share->write == 1) {
sleep(1);
printf("Waiting the read process!!!\n");
}
printf("please input hello world!!!\n");
fgets(str,MAXSIZE,stdin);
sprintf(share->buffer,"%s",str);
share->write = 1;
if(strncmp(str,"end",3) == 0)
break;
sleep(1);
}
if(shmdt(shmptr) < 0)
perror("shmdt");
exit(0);
return 0;
}
30)进程A向消息队列发送消息“hello,world”,进程B从消息队列读取消息,并打印。进程C向消息队列发送“自己在姓名”,进程D从消息队列中取出姓名字符串,并打印
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/types.h>
struct msg {
char msg_str[128];
};
int main() {
int qid;
struct msg mymsg;
if(qid = msgget(0x66,0666|IPC_CREAT) < 0)
perror("msgget");
int pid;
pid = fork();
if(pid < 0)
perror("fork");
else if(pid == 0) {
printf("This is A process!\n");
sprintf(mymsg.msg_str,"hello world");
if(msgsnd(qid,&mymsg,128,0) < 0)
perror("msgsnd");
} else {
if(fork() == 0) {
printf("This is B process!\n");
if(msgrcv(qid,&mymsg,128,0,0) < 0)
perror("msgrcv");
printf("The msg is: %s\n",mymsg.msg_str);
} else if(fork() == 0) {
printf("This is the C process!\n");
sprintf(mymsg.msg_str,"someonename");
if(msgsnd(qid,&mymsg,128,0) < 0)
perror("msgsnd");
} else {
printf("This is D process!\n");
if(msgrcv(qid,&mymsg,128,0,0) < 0)
perror("msgrcv");
printf("The msg is: %s\n",mymsg.msg_str);
}
}
return 0;
}