Linux高级进程间通信:纪录锁

加锁与解锁


/* lockit---demonstration of fcntl locking */
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>

int main(void)
{
    int fd;
    struct flock my_lock;

    /*set the parameters for the write lock*/
    my_lock.l_type=F_WRLCK;
    my_lock.l_whence=SEEK_SET;
    my_lock.l_start=0;
    my_lock.l_len=10;

    /* open file */
    fd=open("locktest",O_RDWR);

    /*lock first ten bytes */
    if(fcntl(fd,F_SETLKW,&my_lock)==-1)
    {
    perror("parent:locking");
        exit(1);
    }

    printf("parent:locked record /n");

    switch(fork())
    {
        case -1:
            perror("fork");
            exit(1);
        case 0:
            my_lock.l_len=5;
            if(fcntl(fd,F_SETLKW,&my_lock)==-1)
            {
                perror("child:locking");
                exit(1);
            }

            printf("child:locked/n");
            printf("child:exiting/n");
            exit(0);
    }

    sleep(5);

    /*now parent releases lock before exiting */
    printf("parent:unlocking/n");
    my_lock.l_type=F_UNLCK;
    if(fcntl(fd,F_SETLK,&my_lock)==-1)
    {
        perror("parent:unlocking");
        exit(1);
    }

    /* now parent exiting */
    
    printf("parent:exiting/n");
    exit(0);
}



/*
    jiang@jiang-linux:~/unixprog/2011322$ gcc lookit.c -o lookit;./lookit
parent:locked record
parent:unlocking
parent:exiting
child:locked
child:exiting

*/





父子进程相互等待,进入死锁状态

#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>

int main(void)
{
    int fd;
    struct flock first_lock;
    struct flock second_lock;

    first_lock.l_type=F_WRLCK;//write lock
    first_lock.l_whence=SEEK_SET;
    first_lock.l_start=0;
    first_lock.l_len=10;

    second_lock.l_type=F_WRLCK;
    second_lock.l_whence=SEEK_SET;
    second_lock.l_start=0;
    second_lock.l_len=10;

    fd=open("locktest",O_RDWR);

    if(fcntl(fd,F_SETLKW,&first_lock)==-1)
    {
        fatal("first_lock");
    }

    printf("lock succeeded (proc %d )/n",getpid());

    switch(fork())
   {
         case -1:
             /*error*/
             fatal("fork call");
         case 0:
             /*child*/
             if(fcntl(fd,F_SETLKW,&second_lock)==-1)//second lock
             {
                 fatal("second lock");
             }

             printf("second lock succeeded (proc%d)/n",getpid());
             
       
             if(fcntl(fd,F_SETLKW,&second_lock)==-1)  //first lock
             {
                 fatal("second lock");
             }
         default:
             /*parent*/
             printf("parent sleeping/n");
             sleep(5);
             if(fcntl(fd,F_SETLKW,&second_lock)==-1)//lock child's lock
             {
                 fatal("child lock second lock:child already lock");
             }

             printf("second lock succeeded (proc %d)/n",getpid());
     }
}


int fatal(char *s)
{
    perror(s);
    exit(1);
}



/*进入死锁状态了,似乎系统并不会自动检测2个死锁的。
    jiang@jiang-linux:~/unixprog/2011322$ gcc deadlock.c -o deadlock.o;./deadlock.o
lock succeeded (proc 3023 )
parent sleeping
second lock succeeded (proc 3023)
second lock succeeded (proc3024)
parent sleeping
jiang@jiang-linux:~/unixprog/2011322$ second lock succeeded (proc 3024)
^C

*/

### 创建基于C语言的学生信息管理系统 #### 文件结构规划 为了便于管理和维护,建议将整个项目分为多个源文件和头文件。通常情况下,会有一个`main.c`作为入口文件,以及一些功能模块对应的`.c`和`.h`文件用于定义数据结构、函数声明及其具体实现。 对于学生信息系统而言,可以考虑如下简单的目录布局: - `student_info/`: 项目的根目录。 - `include/`: 放置公共使用的头文件。 - `student.h`: 定义学生的数据结构及相关操作接口。 - `src/`: 存放各个功能模块的具体实现代码。 - `main.c`: 主程序逻辑所在位置。 - `student.c`: 实现对学生记录的各种增删改查等功能。 - `Makefile`: 编写规则以便于自动化构建工程[^2]。 #### 数据结构设计 采用结构体来表示单个学生的信息是最直观的方式之一。下面给出一个基本版的数据模型示例: ```c // student.h 中的内容 #ifndef STUDENT_H_ #define STUDENT_H_ typedef struct { char name[50]; /* 姓名 */ int age; /* 年龄 */ float score; /* 成绩 */ } Student; /* 函数原型声明 */ void add_student(Student *s); Student* find_student_by_name(const char *name); int delete_student(const char *name); void update_student_score(const char *name, float newScore); #endif //STUDENT_H_ ``` 这里只列举了一些常见的字段;实际应用中可根据需求调整这些成员变量或者增加更多属性。 #### 功能实现要点 针对上述提到的功能点,在`student.c`里面分别实现了相应的算法逻辑。比如添加新纪录时要检查重复项防止覆盖已有数据;查找特定对象则可通过遍历已有的列表直到找到匹配为止等等。需要注意的是,由于当前仅限于入门级练习所以暂时忽略了持久化存储的问题——即每次运行结束后所有变更都会丢失。如果想要保存更改,则需引入外部数据库支持或是利用本地磁盘文件系统完成读取与写入动作。 #### 调试技巧提示 当遇到难以定位错误的情况时,可以通过gcc自带工具链辅助排查问题。例如使用带有-g选项编译出来的二进制文件配合gdb调试器能够帮助开发者更清晰地了解内部状态变化情况;而像valgrind这样的第三方软件也可以用来检测内存泄漏等问题[^1][^3]。 #### 进程间通信注意事项 考虑到本案例属于单一应用程序范畴之内,并不需要涉及到跨进程通讯机制。不过值得注意的是,在其他场景下不同进程之间确实无法直接访问对方私有空间内的资源(如局部变量),此时便需要用到诸如管道(Pipe)、消息队列(Message Queue)或者是共享内存(Shared Memory Segment)等高级特性才能达成目的[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值