C基础常用代码
1. 写文件
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> //write ASCII value int file_write(char *fn, int val) { int fd, ret; char buff[16] = {0}; sprintf(buff, "%d", val); //change int to ASCII string val fd = open(fn, O_RDWR); if (fd < 0) { fprintf(stderr,"my_debug: open %s failed: %s\n", fn, strerror(errno)); return -1; } ret = write(fd, buff, strlen(buff)); if (ret < 0) { fprintf(stderr,"my_debug: write %s failed: %s\n", fn, strerror(errno)); return -1; } close(fd); return 0; } void main() { file_write("tmp.txt", 111); }
2. 读文件
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> int file_read(char *fn) { int fd, ret; ssize_t count = 0; char buff[257]; fd = open(fn, O_RDWR); if (fd < 0) { fprintf(stderr,"open %s failed: %s\n", fn, strerror(errno)); return -1; } do { int ret = read(fd, buff, sizeof(buff)-1); if (!ret) break; count += ret; buff[ret] = 0; printf("%s", buff); } while (ret); printf("data count=%ld\n", count); } int main() { file_read("tmp.txt"); return 0; }
3. 使用信号
#include <stdio.h> #include <signal.h> #include <unistd.h> void sig_handler(int sig) { printf("sig=%d\n", sig); return; } int main() { if (signal(SIGCHLD, sig_handler) == SIG_ERR) { printf("signal error"); } printf("Parent loop\n"); while (1) sleep(1); }
3.1 监控信号
/* * kill -l 可查看各个信号的值。 * kill -9 还是可杀掉,且信号值打印不出来,不可捕捉。 */ #include <stdio.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> int smenu[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 }; #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) int g_choice; void sig_handler(int sig) { printf("Ham: Caught signal %d\n", sig); if (g_choice == 0) { exit(1); } } int main(int argc, char *argv) { int i; if (argc > 1) g_choice = 1; for (i = 0; i < ARRAY_SIZE(smenu); i++) { signal(smenu[i], sig_handler); } while(1) { sleep(1); } return 0; }
4. dup()&execv()实验
4.1. dup_test.c
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> int main() { int fd_1, fd_2; pid_t pid; fd_1 = open("tmp.txt", O_RDWR); if (fd_1 < 0) { fprintf(stderr,"my_debug: open failed: %s\n", strerror(errno)); return -1; } fprintf(stderr,"1: fd_1=%d\n", fd_1); /* dup fd */ fd_2 = fcntl(fd_1, F_DUPFD_CLOEXEC, 0); fprintf(stderr,"2: fd_2=%d\n", fd_2); pid = fork(); if (pid == 0) { /* must null terminal */ char *args[] = {"600", NULL}; pid_t child = getpid(); fprintf(stderr, "child pid=%d\n", child); //注: child同样存在两个fd #if 1 /* 这里若不执行会提前退出,所有者会变成系统,但是打开的文件还是不会关闭 */ if(execv("./execv_test", args) < 0) { fprintf(stderr,"execv failed: %s\n", strerror(errno)); return -1; } #endif } else { pid_t parent = getpid(); fprintf(stderr,"parent pid=%d\n", parent); } sleep(600); return 0; }
4.2. execv_test.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void main(int argc, char *argv[]) { int sleep_time; printf("execv: I am execv child process.\n"); /* execv: argc=1, argv[0]=600, argv[1]=(null). 不同于命令行,这个argv[0]就是参数 */ printf("execv: argc=%d, argv[0]=%s, argv[1]=%s.\n", argc, argv[0], argv[1]); if (argc == 1) { sleep_time = atoi(argv[0]); printf("execv: enter sleep %ds.\n", sleep_time); sleep(sleep_time); } }
4.3. 打印内容
(1) 只fork:
/proc$ ls 1307/fd -l //parent lrwx------ 1 ham ham 64 1月 7 14:20 3 -> /data/ham/file_161/4.c_test/15.dup_test/tmp.txt lrwx------ 1 ham ham 64 1月 7 14:20 4 -> /data/ham/file_161/4.c_test/15.dup_test/tmp.txt /proc$ /proc$ ls 1308/fd -l //child lrwx------ 1 ham ham 64 1月 7 14:20 3 -> /data/ham/file_161/4.c_test/15.dup_test/tmp.txt lrwx------ 1 ham ham 64 1月 7 14:20 4 -> /data/ham/file_161/4.c_test/15.dup_test/tmp.txt
可以看到 fork() 后子进程继承父进程所有打开的文件,且文件fd不会自动关闭。
(2) fork后执行execv:
/proc$ ls 47209/fd -l lrwx------ 1 ham ham 64 1月 7 14:45 3 -> /data/ham/file_161/4.c_test/15.dup_test/tmp.txt lrwx------ 1 ham ham 64 1月 7 14:45 4 -> /data/ham/file_161/4.c_test/15.dup_test/tmp.txt /proc$ /proc$ ls 47210/fd -l lrwx------ 1 ham ham 64 1月 7 14:45 3 -> /data/ham/file_161/4.c_test/15.dup_test/tmp.txt
可以看到 execv() 后子进程继承父进程的通过 fcntl(fd_1, F_DUPFD_CLOEXEC, 0) dump出来的fd已经自动关闭了,只剩下一个没有关闭。进一步实验,即使父进程中执行execv(),其dup出来的fd也会自动关闭。
posted on 2023-12-08 15:00 Hello-World3 阅读(52) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2021-12-08 调度器19—/proc/sched_debug文件
2021-12-08 调度器18—/proc/schedstat文件
2021-12-08 VFS虚拟文件系统
2021-12-08 给Linux内核提交代码
2018-12-08 selinux操作
2018-12-08 /proc/sys/vm/drop_caches 清理缓存
2018-12-08 aircrack-ng 工具集学习