添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

2.两个进程可以任意对文件进行读写操作,操作系统并不保证写的原子性

3.进程可以通过系统调用对文件加锁,从而实现对文件内容的保护

4.任何一个进程删除该文件时,另外一个进程不会立即出现读写失败

5.两个进程可以分别读取文件的不同部分而不会相互影响

6.一个进程对文件长度和内容的修改另外一个进程可以立即感知

二:文件描述符与打开文件的关系?
在这里插入图片描述
内核中,对应于每个进程都有一个文件描述符表,表示这个进程打开的所有文件。文件描述表中每一项都是一个指针,指向一个用 于描述打开的文件的数据块———file对象,file对象中描述了文件的打开模式,读写位置等重要信息,当进程打开一个文件时,内核就会创建一个新的file对象。需要注意的是,file对象不是专属于某个进程的,不同进程的文件描述符表中的指针可以指向相同的file对象,从而共享这个打开的文件。file对象有引用计数,记录了引用这个对象的文件描述符个数,只有当引用计数为0时,内核才销毁file对象,因此某个进程关闭文件,不影响与之共享同一个file对象的进程。

文章参考: https://blog.csdn.net/weibo1230123/article/details/83045458

一:结论1.两个进程中分别产生生成两个独立的fd2.两个进程可以任意对文件进行读写操作,操作系统并不保证写的原子性3.进程可以通过系统调用对文件加锁,从而实现对文件内容的保护4.任何一个进程删除该文件时,另外一个进程不会立即出现读写失败5.两个进程可以分别读取文件的不同部分而不会相互影响6.一个进程对文件长度和内容的修改另外一个进程可以立即感知二:文件描述符与打开文件的关系?内核...
在看Android 源码的时候能看到Binder驱动 打开 文件 路径统一都是:"/dev/binder" 然后看到每 一个 ProcessStated初始化的时候会调用:mDriverFD(open_driver(driver)), 有点疑惑 同一个 Linux 文件 被不同的 进程 、相同 进程 同时 打开 (均以读写方式)会有什么效果。 写了点测试代码: #include <stdio.h> #include <sys/types.h> #include <sys/stat.h>
实验目标:在 Linux 内核中增加 一个 系统调用,并编写对应的 linux 应用程序。利用该系统调用能够遍历系统当前所有 进程 的任务描述符,并按 进程 父子 关系 将这些描述符所对应的 进程 id(PID)组织成树形结构显示。 实验环境: Ubuntu 20.04.03 LTS,Kernel Version 5.13.0(截至2022年2月18日Ubuntu官网最新LTS版本) 实验结果: 成功实现该实验目标,网上很多示例都是老版本内核的写法,在新版本内核系统上不适用,踩了很多坑 文件 内容: 实验相关源码 文件 、源码使用说明、环境配置说明
Linux 守护 进程 Linux 的后台服务 进程 ,相当于Windows服务,对于为 Linux 开发服务程序的朋友来说, Linux 守护 进程 相关技术是必不可少的,因为这个技术不仅仅是为了开发守护 进程 ,还可以拓展到多 进程 ,父子 进程 文件描述符 共享,父子 进程 通讯、控制等方面,是实现 Linux 大型服务的基础技术之一。 如果要在Red Hat Enterprise Linux 上将.NET Core 进程 作为后台 进程 运行,则可以创建自定义systemd单元。今天我将为.NET Core编写两个自定义系统单元的例子。 一个 是运行.NET Core控制台应用程序的一种类型,另 一个 是运行ASP.NET Core Web
Python的多线程在io方面比单线程还是有优势,但是在多线程开发时,少不了对 文件 的读写操作。在管理 多个 线程对同一 文件 的读写操作时,就少不了 文件 锁了。 使用fcntl 在 linux 下,python的标准库有现成的 文件 锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。 对于 文件 锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。 其中,参数 fd 表示 文件描述符 ;参数 operation 指定要进行的锁操作,该参数的取值有如下几种: LOCK_SH:表示要创建 一个 共享锁,在任意时间内, 一个 文件 的共享锁可以被 多个 进程 拥有
同一个 文件 可以被多次 打开 ,譬如在 一个 进程 中多次 打开 同一个 文件 、在 多个 不同的 进程 打开 同一个 文件 。 ⚫ 一个 进程 内多次 open 打开 同一个 文件 ,那么会得到 多个 不同的 文件描述符 fd,同理在关闭 文件 的时候也需要调用 close 依次关闭各个 文件描述符 。 多次 打开 同一个 文件 测试代码 1 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h>
一直苦恼 一个 问题:shell编程中,当 一个 任务完成时,接下来可以同时有两个任务可以运行,这两个任务互不影响。所以想当第 一个 任务完成后,同时启动后面的两个任务,不知到shell中如何同时启动。 今天解决了:使用后台运行的方式 &。 举个例子说明比较好。 有 一个 总执行的all.sh,有三个任务shell,分别是aa.sh, bb.sh,cc.sh。 当运行玩aa.sh后,同时运行bb.
IPC是 进程 间通信(interprocess communication)的简称。传统上该术语描述的是运行在某 个操作系统之上的不同 进程 间各种消息传递(message passing)的方式。本书还讲述多种形式 的同步(synchronization),因为像共享内存区这样的较新式的通信需要某种形式的同步参与 ......
代码如下: #!/bin/bash SEND_THREAD_NUM=13 tmp_fifofile=”/tmp/$$.fifo” # 脚本运行的当前 进程 ID号作为 文件 名 mkfifo “$tmp_fifofile” # 新建 一个 随机fifo管道 文件 exec 6<>”$tmp_fifofile” # 定义 文件描述符 6指向这个fifo管道 文件 rm $tmp_fifofile for ((i=0;i<$SEND_THREAD_NUM;i++));do echo # for循环 往 fifo管道 文件 中写入13个空行 done >&6 for i in `seq 100`;do # 100 次 fo
本文研究的主要是 Linux 通过匿名管道进行 进程 间通信的相关内容,具体介绍如下。 在前面,介绍了一种 进程 间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是 一个 信号值。这里将介绍另一种 进程 间通信的方式——匿名管道,通过它 进程 间可以交换更多有用的数据。 一、什么是管道 如果你使用过 Linux 的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号“|”来使用管道,但是管理的真正定义是什么呢?管道是 一个 进程 连接数据流到另 一个 进程 的通道,它通常是用作把 一个 进程 的输出通过管道连接到另 一个 进程 的输入。 举个例子,在shell中输入命令:ls -l | grep st
1,父 进程 listen,创建pipe(下面所有父子 进程 之间的通信都用该pipe) 2,父 进程 预fork n个子 进程 3,各个子 进程 accept(listenfd),即所有子 进程 竞争accept请求。由于listenfd是在fork之前就有的,所以所有子 进程 都可以访问到,不需用到“ 进程 文件描述符 传递”问题; 4,子 进程 每accept到 一个 请求都告诉父 进程 ,父 进程 把请求数加1;子 进程 没完成 一个 请求,父 进程 把请求数减1;当父 进程 发现请求数 >= 子 进程 数时,父 进程 创建新的子 进程 ,并把子 进程 数加1(当然子 进程 数有个预先上限);当父 进程 发现子 进程 数大于请求数加1时,父 进程 杀死多余的子 进程 。 总的来说,思想是让子 进程 accept并处理请求,父 进程 通过子 进程 发来的信息控制请求数与子 进程 数之间的 关系 。 代码如下: 代码如下: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PRECHILD 5 #define MAXCHILD 50 #define BUFSIZE 4096 #define PIDPATH "pid" #define head503 "HTTP/1.1 503 Service unavailable\r\n" #define head404 "HTTP/1.1 404 Not Found\r\n" #define head200 "HTTP/1.1 200 0K\n\rContent—Type: text/html\n\rContent—Length: " int len503, len404, len200; int fd1[2], fd2[2]; typedef struct { pid_t pid; char status; // 'n' means new request; 'f' means finish the request } REPORT; void answer(int listenfd) int connfd; char buf[BUFSIZE]; int count; int pid = getpid(); struct sockaddr_in cliaddr; int size = sizeof(cliaddr); char comm; REPORT rep; rep.pid = pid; while (1) { connfd = accept(listenfd, (struct sockaddr *)&cliaddr,(socklen_t *)&size ); //子 进程 accept请求 rep.status = 'n'; if (write(fd1[1], &rep, sizeof(rep)) 0) { //printf("%s", content); if (write(connfd, content, count) != count) { printf("write failed\n"); fclose(fp); close(connfd); rep.status = 'f'; if (write(fd1[1], &rep, sizeof(rep)) < 0) {//告诉父 进程 自己处理完了请求 perror("write pipe finish failed"); exit(-1); if (read(fd2[0], &comm, 1) < 1) {//等待来自父 进程 的命令 perror("read pipe failed"); exit(-1); //printf("[%d] reve %c from pa\n", pid, comm); if (comm == 'e') { //收到exit命令 printf("[%d] exit\n", pid); exit(-1); else if (comm == 'c') { //收到继续accept的命令 printf("[%d] continue\n", pid); else { printf("[%d] comm : %c illeagle\n", pid, comm); void usage() printf("Usage: http-serv port\n"); int write_pid() int fd; if ((fd = open(PIDPATH, O_WRONLY | O_TRUNC | O_CREAT, S_IWUSR)) < 0){ perror("open pidfile faild"); return -1; struct flock lock; lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; if (fcntl(fd, F_SETLK, &lock) == -1) { int err = errno; perror("fcntl faild"); if (err == EAGAIN) { printf("Another http-serv process is running now!\n"); return -1; return 0; void daemon_init() //clear file creation mask; umask(0); //become a session leader if (fork() != 0) exit(-1); if (setsid() < 0) exit(-1); //make sure can be never get the TTY control if (fork() != 0) exit(-1); //may chdir here int i; for (i = 0; i < 1024; i++) close(i); * Attach file descriptors 0, 1, and 2 to /dev/null. int fd0, fd1, fd2; fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); if (fd0 != 0 || fd1 != 1 || fd2 != 2) { printf("init failed\n"); exit(-1); main(int argc, char **argv) int listenfd; struct sockaddr_in servaddr; pid_t pid; if (argc != 2) { usage(); return -1; signal(SIGCHLD, SIG_IGN); len200 = strlen(head200); len404 = strlen(head404); len503 = strlen(head503); daemon_init(); //转为后台程序,如需打印调试,把这行注释掉 if (write_pid() < 0) //避免同时有 多个 该程序在运行 return -1; if (pipe(fd1) < 0) { perror("pipe failed"); exit(-1); if (s_pipe(fd2) < 0) { perror("pipe failed"); exit(-1); int port = atoi(argv[1]); //initialize servaddr and listenfd... bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(port); listenfd = socket(AF_INET, SOCK_STREAM, 0); bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); listen(listenfd, 1000); int i; for (i = 0; i < PRECHILD ; i++) { //父 进程 预fork 子 进程 if ((pid = fork()) < 0) { perror("fork faild"); exit(3); else if (pid == 0) { answer(listenfd); else { printf("have create child %d\n", pid); char e = 'e'; char c = 'c'; int req_num = 0; int child_num = PRECHILD; REPORT rep; while (1) { //printf("req_num = %d, child_num = %d\n", req_num, child_num); if (read(fd1[0], &rep, sizeof(rep)) = child_num && child_num <= MAXCHILD) { //请求数过多,创建更多子 进程 if ((pid = fork()) (req_num + 1) && child_num > PRECHILD) {//子 进程 数过多,删除多余的子 进程 if (write(fd2[1], &e, sizeof(e)) < sizeof(e)) { perror("pa write pipe failed"); exit(-2); //printf("tell child exit\n"); child_num --; else { if (write(fd2[1], &c, sizeof(c)) < sizeof(c)) {//让子 进程 继续等待accept perror("pa write pipe failed"); exit(-2); //printf("tell child continue\n"); return 0; 利用fork()创建 多个 进程 11:09 pm on Oct 23rd 2010 greenMay 之间我学习了创建 一个 进程 ,也大致理解了子 进程 与父 进程 关系 。今天无意间遇到 一个 创建 多个 进程 的问题,结果还发现了点小bug,现在写下来和大家分享。 我需要实现的目标如下:编写一段源程序,使系统调用fork()创建两个子 进程 ,当此程序运行时,在系统中有 一个 进程 和两个子 进程 活动。让每 一个 进程 在屏幕上显示 一个 字符:父 进程 显示字符“a”;子 进程 分别显示字符“b”和字符“c”。 一开始我的主要代码如下: view source print? 01 int main() 03 pid_t child1; 04 pid_t child2; 05 child1 = fork(); 06 child2 = fork(); 07 if(child1 == 0) 08 { 09 printf("Child1:a\n"); 10 return 0; 11 } 12 if(child2 == 0) 13 { 14 printf("Child2:b\n"); 15 return 0; 16 } 17 else 18 { 19 waitpid(child1,NULL,0); 20 waitpid(child2,NULL,0); 21 printf("Parent:c\n"); 22 } 23 return 0; 奇怪的是,我得到的是这样 一个 结果: Child1:a Child1:a Child2:b Parent:c 竟然有两个Child1。可是我的代码里明明只是让Chidl1打印一次啊。搜索到一篇好的博文。文章仔细分析了和我几乎相同的情况。事实上,是我的粗心和对fork()的理解不深刻导致了上述的奇怪问题。 我们知道,fork()之后,我们还是首先执行的是父 进程 ,也就是如下代码段: view source print? 1 waitpid(child1,NULL,0); 2 waitpid(child2,NULL,0); 3 printf("Parent:c\n"); 然后waitpid(child1,NULL,0),进入child1的执行。child1将要执行的是如下的的代码段: view source print? 1 child2 = fork(); 2 if(child1 == 0) 4 printf("Child1:a\n"); 5 return 0; 注意,第一行的那个child2 = fork()!这就意味着对于child1来说,它自己又要创建 一个 进程 ,这时候他成为了父亲。这时候,它有 一个 儿子child2,但是这个child2不同与我们刚才定义的那个child2,这个child2其实是parent的孙子。之所以又打印了一边Child1。如果加上如下代码就明白了: view source print? 01 child2 = fork(); 02 if(child1 == 0) 03 { 04 if(child2 == 0) 05 { 06 printf("GrandChild!\n"); 07 } 08 printf("Child1:a\n"); 09 return 0; 10 } 这时候将出现: Child1:a GrandChild! Child1:a Child2:b Parent:c 恩,这就很明白了!我无意间多调用了一次child2=fork(); 所以,如果要达到我最初的目的,需要改变child2的fork()的位置: view source print? 01 #include 02 #include 03 #include 04 #include 05 int main() 07 pid_t child1; 08 pid_t child2; 09 child1 = fork(); 10 child2 = fork(); 11 if(child1 == 0) 12 { 13 printf("Child1:a\n"); 14 return 0; 15 } 16 if(child2 == 0) 17 { 18 printf("Child2:b\n"); 19 return 0; 20 } 21 else 22 { 23 waitpid(child1,NULL,0); 24 waitpid(child2,NULL,0); 25 printf("Parent:c\n"); 26 } 27 return 0; 我参照的那个博文最后给出了 一个 更为普遍的fork()创建多 进程 的程序框架: view source print? 01 pid_t create_child() 03 pid_t p = fork(); 04 if( p == 0 ) 05 { 06 printf("in child %d\n", getpid()); 07 //do something 08 return 0; 09 } 10 return p; 12 int main(void) 14 pid_t p1 = create_child(); 15 pid_t p2 = create_child(); 17 int st1, st2; 18 waitpid( p1, &st1, 0); 19 waitpid( p2, &st2, 0); 20 printf("in parent, pid = %d\n", getpid()); 21 printf("in parent, child 1 exited with %d\n", st1); 22 printf("in parent, child 2 exited with %d\n", st2); 23 return 0; 注意到,期中的create_child()函数最后有 一个 return p。这个return p将pid返回给了父 进程 ,其实也是将子 进程 对于CPU的控制权交还给了父 进程 ,这样就避免了 多个 进程 在创建之时互相影响了。 可以说,今天的这个问题真是 一个 有趣的事情。代码有的时候就是这么奇怪~ 最后,向我引用的那篇文章致敬! Linux 内核对多 进程 和多线程的支持方式: 线程机制支持并发程序设计技术,在多处理器上能真正保证并行处理。而在 linux 实现线程很特别, linux 把所有的线程都当作 进程 实现。 linux 下线程看起来就像普通 进程 (只是该 进程 和其他 进程 共享资源,如地址空间)。上述机制与Microsoft windows或是Sun Solaris实现差异很大。 Linux 的线程实现是在核外进行的,核内提供的是创建 进程 的接口do_fork()。内核提供了两个系统调用__clone()和fork(),最终都用不同的参数调用do_fork()核内API。 do_fork() 提供了很多参数,包括CLONE_VM(共享内存空间)、CLONE_FS(共享 文件 系统信息)、CLONE_FILES(共享 文件描述符 表)、CLONE_SIGHAND(共享信号句柄表)和CLONE_PID(共享 进程 ID,仅对核内 进程 ,即0号 进程 有效)。当使用fork系统调用产生多 进程 时,内核调用do_fork()不使用任何共享属性, 进程 拥有独立的运行环境。当使用pthread_create()来创建线程时,则最终设置了所有这些属性来调用__clone(),而这些参数又全部传给核内的do_fork(),从而创建的” 进程 ”拥有共享的运行环境,只有栈是独立的,由 __clone()传入。 即: Linux 下不管是多线程编程还是多 进程 编程,最终都是用do_fork实现的多 进程 编程,只是 进程 创建时的参数不同,从而导致有不同的共享环境。 Linux 线程在核内是以轻量级 进程 的形式存在的,拥有独立的 进程 表项,而所有的创建、同步、删除等操作都在核外pthread库中进行。pthread 库使用 一个 管理线程(__pthread_manager() ,每个 进程 独立且唯一)来管理线程的创建和终止,为线程分配线程ID,发送线程相关的信号,而主线程pthread_create()) 的调用者则通过管道将请求信息传给管理线程。 很多朋友都说使用多线程的好处是资源占用少,其隐含之意就是说 进程 占用资源比线程多,对吧?但实际上 Linux 下多 进程 是否就真的点用很多资源呢?暂且不说 进程 是否比线程占用资源多,就 进程 占用资源的多少情况而言, Linux 确实是做得相当节省的。产生 一个 进程 时肯定是要产生的一点内存是要复制 进程 表项,即 一个 task_struct结构,但这个结构本身做得相当小巧。其它对于 一个 进程 来说必须有的数据段、代码段、堆栈段是不是全盘复制呢?对于多 进程 来说,代码段是肯定不用复制的,因为父 进程 和各子 进程 的代码段是相同的,数据段和堆栈段呢?也不一定,因为在 Linux 里广泛使用的 一个 技术叫copy-on-write,即写时拷贝。copy-on-write意味着什么呢?意味着资源节省,假设有 一个 变量x在父 进程 里存在,当这个父 进程 创建 一个 进程 多个 进程 时这个变量x是否复制到了子 进程 的内存空间呢?不会的,子 进程 和父 进程 使用 同一个 内存空间的变量,但当子 进程 或父 进程 要改变变量x的值时就会复制该变量,从而导致父子 进程 里的变量值不同。父子 进程 变量是互不影响的,由于父子 进程 地址空间是完全隔开的,变量的地址可以是完全相同的。 Linux 的”线程”和” 进程 ”实际上处于 一个 调度层次,共享 一个 进程 标识符空间,这种限制使得不可能在 Linux 上实现完全意义上的POSIX线程机制,因此众多的 Linux 线程库实现尝试都只能尽可能实现POSIX的绝大部分语义,并在功能上尽可能逼近。 Linux 进程 的创建是非常迅速的。内核设计与实现一书中甚至指出 Linux 创建 进程 的速度和其他针对线程优化的操作系统(Windows,Solaris)创建线程的速度相比,测试结果非常的好,也就是说创建速度很快。由于异步信号是内核以 进程 为单位分发的,而 Linux Threads的每个线程对内核来说都是 一个 进程 ,且没有实现”线程组”,因此,某些语义不符合POSIX标准,比如没有实现向 进程 中所有线程发送信号,README对此作了说明。 Linux Threads中的线程同步很大程度上是建立在信号基础上的,这种通过内核复杂的信号处理机制的同步方式,效率一直是个问题。 Linux Threads 的问题,特别是兼容性上的问题,严重阻碍了 Linux 上的跨平台应用(如Apache)采用多线程设计,从而使得 Linux 上的线程应用一直保持在比较低的水平。在 Linux 社区中,已经有很多人在为改进线程性能而努力,其中既包括用户级线程库,也包括核心级和用户级配合改进的线程库。目前最为人看好的有两个项目, 一个 是RedHat公司牵头研发的NPTL(Native Posix Thread Library),另 一个 则是IBM投资开发的NGPT(Next Generation Posix Threading),二者都是围绕完全兼容POSIX 1003.1c,同时在核内和核外做工作以而实现多对多线程模型。这两种模型都在一定程度上弥补了 Linux Threads的缺点,且都是重起炉灶全新设计的。 综上所述的结论是在 Linux 下编程多用多 进程 编程少用多线程编程。 IBM有个家伙做了个测试,发现切换线程context的时候,windows比 linux 快一倍多。进出最快的锁(windows2k的 critical section和 linux 的pthread_mutex),windows比 linux 的要快五倍左右。当然这并不是说 linux 不好,而且在经过实际编程之后,综合来看我觉得 linux 更适合做high performance server,不过在多线程这个具体的领域内, linux 还是稍逊windows一点。这应该是情有可原的,毕竟unix家族都是从多 进程 过来的,而 windows从头就是多线程的。 如果是UNIX/ linux 环境,采用多线程没必要。 多线程比多 进程 性能高?误导! 应该说,多线程比多 进程 成本低,但性能更低。 在UNIX环境,多 进程 调度开销比多线程调度开销,没有显著区别,就是说,UNIX 进程 调度效率是很高的。内存消耗方面,二者只差全局数据区,现在内存都很便宜,服务器内存动辄若干G,根本不是问题。 多 进程 是立体交通系统,虽然造价高,上坡下坡多耗点油,但是不堵车。 多线程是平面交通系统,造价低,但红绿灯太多,老堵车。 我们现在都开跑车,油(主频)有的是,不怕上坡下坡,就怕堵车。 高性能交易服务器中间件,如TUXEDO,都是主张多 进程 的。实际测试表明,TUXEDO性能和并发效率是非常高的。TUXEDO是贝尔实验室的,与UNIX同宗,应该是对UNIX理解最为深刻的,他们的意见应该具有很大的参考意义 2010年7月10日08:43 回复 | 引用 | #1 文章很有深度,我们把握 一个 尺度就可以了,在windows下使用线程,unix下则使用 进程 就可以了 2010年9月9日13:49 回复 | 引用 | #2 错的太多了,博主,应该看看新资料了。 现在都2010年了,NPTL早就取代了老的 Linux thread。而且通常多线程有性能优势,但是多 进程 更稳定,并且通常性能瓶颈不在于是 进程 模型还是线程模型而在于IO。 2010年9月9日13:56 回复 | 引用 | #3 关于那个critical section和pthread_mutex_t,critical section本质上是 一个 自旋锁,短期锁当然快,不知道你说的那个IBM的哥们怎么比的,要比也该是和pthread_spinlock_t比。 admin 2010年9月9日17:28 回复 | 引用 | #4 rjoo挺热心的,呵呵,这篇文章不是我写的,但有几个地方我可以解答一下: 1. Linux 下没有线程的概念,pthread线程实质是通过轻量级 进程 实现的。你说瓶颈在IO,这一点我很赞同你的意见,作者如果能再写个IO操作的文章来的话就会更好了。 2. mutex和critical section的确是不能比的。 一个 涉及到内核, 一个 没有涉及到内核。呵呵,很佩服你对这些东西的掌握程度,有机会多交流。 2010年9月9日17:40 回复 | 引用 | #5 我们组的最近项目的经验告诉我们能用多 进程 不用多线程,多线程安全编程难,而且锁会早成效率很低,甚至不如单线程,你说的NPTL我知道,他只是多线程优化了并不能改变多线程安全编程的问题,锁的问题。谢谢指教,实践出真知。 @rjoo 2010年9月9日17:44 回复 | 引用 | #6 你说的锁,我确实不太了解,但是我们leader对它很了解,就是最近的 一个 项目,锁搞得他很郁闷,他也终于同意我的关键,尽可能不用多线程。 @rjoo 2010年9月29日13:41 回复 | 引用 | #7 @admin Linux 下没有线程的概念,pthread线程实质是通过轻量级 进程 实现的—这是2.4内核以前的情况(实际上是2.0时引入的,那可实在是太久了),2.4内核引入NGPL,2.6内核线程支持改为NPTL。NPTL实现的是1:1的线程模型(有资料说Win也是这种实现,虽然不太确定,但我觉得可能性很大),而NGPT虽然是理论上最先进的m:n线程模型,但最后实现出来的性能差NPTL一大截,最后被抛弃。看看文中说法就知道要么文章写的很早,要么作者看了一堆十年前的资料。 给个链接: http://www.kegel.com/c10k.html#threads. linux threads finalday 2010年10月15日17:26 回复 | 引用 | #8 忍不住跳出来说,作者对并发编程的理解还不行。 比如说锁的问题,说得好像是多线程才需要的东西一样。如果 一个 应用多 进程 时完全不用锁,多线程也就多 一个 轻量级锁——锁一下,各回各家,每个线程用自己的专有存储,之后不就和多 进程 一样了?这样会被搞得很郁闷?当然不会。所以说明那个应用对于数据共享的需求不是这么简单,既然不是这么简单,多 进程 程序一样要加锁。多 进程 的加解锁代价可比多线程大得多了,共享数据和协作也麻烦多了。 多线程编程难不难?难,但这是由于并发本身的难度引起的。“锁”,“安全编程”不管是多线程还是多 进程 都一样会遇到。 多线程的最大优点是数据共享和协作方便。 多 进程 的最大优点是挂了 一个 进程 不会影响其他 进程 ,资源也不会泄露,故比较能容忍程序员犯错。 至于两者裸奔比性能,真的没啥意义。
1.在继承自bsd的系统可以同时发送 多个 ,其它平台不能。 2.在我的机器上(x86_64bit, linux 2.6.37.6)测试成功,功能函数封装在TransFD.c中. 3.测试过程, 进程 A连续向 进程 B发起tcp连接, 进程 B接收到A的连接, 进程 B把A与B的 多个 连接fd同时发给 进程 C, 进程 C然后一次接收出这些fd并根据数量依次接收每个fd的内容。 --JEF --20110709
对于 多个 进程 打开 同一 文件 的情况,每个 进程 都有它自己的 文件 表项(file对象),其中有它自己的 文件 位移量,所以对于 多个 进程 读同一 文件 都能正确工作。但是,当 多个 进程 写同一 文件 时,则可能产生预期不到的结果。(可以使用pread,pwrite)。 总结:两个独立 进程 打开 同一 文件 ,对应不同的file对象,每个 进程 调用close只影响本 进程 的“ 打开文件 计数”(file对象的引用计数)。 可以先 打开 着...
Linux 文件描述符 一个 整数,用于标识 打开 文件 或其他I/O设备。每个 进程 都有一组 文件描述符 ,它们是 进程 文件 系统、网络和其他I/O设备进行交互的主要方式。 文件描述符 可以是标准输入、标准输出或标准错误,也可以是由 进程 打开 文件 、管道、套接字等。 Linux 文件描述符 的范围是0到最大 文件描述符 数-1,默认情况下最大 文件描述符 数是1024。当 进程 打开 一个 文件 或其他I/O设备时,内核会返回 一个 文件描述符 进程 可以使用该 文件描述符 来读取、写入或关闭 文件 文件描述符 进程 与操作系统之间的接口,它们是 进程 文件 系统、网络和其他I/O设备进行交互的主要方式。 在 Linux 中, 文件描述符 是通过系统调用来创建和管理的。常用的系统调用包括open、read、write、close等。 文件描述符 的使用是非常重要的,因为它们直接影响到 进程 的性能和稳定性。如果 进程 打开 了太多的 文件描述符 ,可能会导致系统资源不足,从而导致 进程 崩溃或系统崩溃。 总之, Linux 文件描述符 进程 文件 系统、网络和其他I/O设备进行交互的主要方式,它们是 进程 与操作系统之间的接口,通过系统调用来创建和管理。 文件描述符 的使用是非常重要的,需要注意 进程 打开 文件描述符 数量,以避免系统资源不足的问题。