Find the answer to your Linux question:
Results 1 to 9 of 9
Hello, I have already used the function msgctl() in user space without any problem, in order to obtain the number of messages in queue from its ID (as shown below): ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Jul 2012
    Posts
    9

    Using msgctl() function in the kernel side


    Hello,
    I have already used the function msgctl() in user space without any problem, in order to obtain the number of messages in queue from its ID (as shown below):

    Code:
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/msg.h>
    #include<stdio.h>
    
    main(int argc, char *argv[])
    {
    	int qid;
    	struct msqid_ds qstatus;
    	
    	qid=(int)atoi(argv[1]);
    
    	if(msgctl(qid,IPC_STAT,&qstatus)<0){
    		perror("msgctl failed");
    		exit(1);
    	}
    	printf("There are %d messages for queue with ID %d\n",qstatus.msg_qnum,qid);
    }
    Now, I need to do the same thing in kernel space, but the code below doesn't work:

    Code:
    int get_num_from_id(int qid){
    
    struct msqid_ds qstatus;
    
    sys_msgctl(qid,IPC_STAT,&qstatus);
    
    return qstatus.msg_qnum;
    }
    What am I doing wrong? Someone can help me, please...

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,558
    In what way is it not working? The sys_msgctl() function returns a long? What is the return value you are getting? What about error codes?
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Just Joined!
    Join Date
    Jul 2012
    Posts
    9
    Hi,
    as you know the aim of the function is to fill the struct msqid_ds with queues information.
    The function returns 0 if it be able to complete this operation regularly, otherwise it returns -1 and sets the variable err wirh the error code. In my case the function alway returns -1 (I have checked the code and the error should be EPERM).
    Last edited by droms; 08-01-2012 at 05:44 AM.

  4. #4
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,558
    Quote Originally Posted by droms View Post
    Hi,
    as you know the aim of the function is to fill the struct msqid_ds with queues information.
    The function returns 0 if it be able to complete this operation regularly, otherwise it returns -1 and sets the variable err wirh the error code. In my case the function alway returns -1 (I have checked the code and the error should be EPERM).
    Your example code doesn't show that you check that. What kernel are you using? If the user-side msgctl() function works with this kernel, then sys_msgctl() on the kernel side must be working because on the 2.6.32 kernel (RHEL 6) they are linked as a system call. I was digging through the kernel headers last night to determine that. So, I can only assume that you are doing something wrong, such as not initializing some kernel data structure. Have you analyzed the actual system call code that is executed when msgctl() talks to the kernel?
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  5. #5
    Just Joined!
    Join Date
    Jul 2012
    Posts
    9
    I'm working with the version 2.6.24 (I can't update version for several reasons) : to solve the problem I have also studied the source code of the function msgctl and I have tried to use the same parts of code in my function (a new scheduler class) but without any result; I have also tried to read directly the struct msq_queue, the same struct read by msgctl but I got the error "segmentation fault" when try to assign the value msq->q_num (msq is the struct msq_queue).

    I have an queue ID and I need to obtain the number of queue elements: any suggest for me? Another way to perform this operation? Thanks in advance

  6. #6
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,558
    Honestly, I'll have to review the 2.6.24 code myself before I can provide more insight. Fortunately, that's the version used by Debian Etch which I use on my ARM development boards, so I have it handy! I'll get back to you as soon as I know a bit more. That may be a few days, so don't stop trying to solve this yourself. If you do sort it out before you hear from me again, please do post the solution here. Thanks.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  7. #7
    Just Joined!
    Join Date
    Jul 2012
    Posts
    9
    OK, thank you so much for the support.

  8. #8
    Just Joined!
    Join Date
    Jul 2012
    Posts
    9
    Hi,
    I have checked my code and the code of the function "sys_msgctl" in the "msg.c" file, but without any result, I always get the same error 665 (EPERM) and I'm becoming crazy.
    If you have found a time to take a look, can you give to me any suggestions (my code is showed below).

    Code:
    static int get_queue_elements(struct nrtp_task *t, int msqid)
    {
    	struct msqid_ds qstatus;
    	int errno, qnumber;
    	
    	if(t){
    		if(errno = sys_msgctl(msqid, IPC_STAT, &qstatus) < 0){
    		if(errno == EACCES) qnumber = 661;
    		if(errno == EFAULT) qnumber = 662;
    		if(errno == EIDRM)  qnumber = 663;
    		if(errno == EINVAL) qnumber = 664;
    		if(errno == EPERM)  qnumber = 665;
    		}
    		else {
    		qnumber = qstatus.msg_qnum;
    		}
    		
    	} 
    	else{
    		printk(KERN_ALERT "get_queue_elements\n");
    	        }		
    
    return qnumber;
    }

  9. #9
    Just Joined!
    Join Date
    Jul 2012
    Posts
    9

    Using msgctl() function in the kernel side

    I have solved the problem, it was the instruction "copy_to_user()" in the function "sys_msgctl()" of "msg.c": it obviously cannot work in kernel space correctly, because the user space addressing is different; I have bypassed the problem by creating another function based on "sys_msgctl()" that takes only "msqid" in input and returns the number of elements... Exactly what I have need!

    Thanks the same to everyone

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •